Getting Started with the Windows App SDK (Preview 2)

As we get closer to the first release of the Windows App SDK, Microsoft has started shipping preview releases. Whilst it’s not clear what “preview” means versus “experimental”, it does appear that the move to shipping releases via the preview channel indicates that we’re getting very close to the v1 stable release. In this post I want to touch on a couple of the APIs that have been added recently, and are important if you want to get started with the Windows App SDK.

Bootstrap

If you’re building a WinUI application the bootstrapping of the Windows App SDK is handled for you, so you don’t need to worry about manually initializing the SDK. However, if you’re integrating the Windows App SDK into a Win32 application (eg WinForms or WPF), you need to explicitly initialize the SDK. For example, you may want to leverage the resource manager as I show in this post.

In the past this was done using code similar to the following:

DO NOT USE THIS CODE
int hr = MddBootstrap.Initialize(0x00010000, "preview2");
if (hr < 0)
{
    MessageBox.Show("Fail to initialize Dynamic Dependencies with error 0x" + hr.ToString("X"), "Error!");
    return;
}

The MddBootstrap was a class that you would define in your application with the Initialize method being a wrapper around a p/invoke to the Bootstrap library eg

DO NOT USE THIS CODE
[DllImport("Microsoft.WindowsAppRuntime.Bootstrap.dll", CharSet = CharSet.Unicode)]
private static extern int MddBootstrapInitialize(uint majorMinorVersion, string versionTag, PackageVersion packageVersion);

The good news, is that you no longer need to add any of this to your application. You still need to initialize the SDK but the SDK provides a .NET projection to make it as simple as calling an Initialize method, specifying the version of the SDK your application requires.

Bootstrap.Initialize(0x00010000, "preview2");

The Initialize method doesn’t return any value, so the only way you can detect if the Initialize failed is to wrap the call in a try-catch.

Luckily, there is an alternative to the Initialize method, which is the TryInitialize method which returns a bool value indicating whether initialization was successful. This is particularly useful if you’re distributing your application unpackaged and need to force the installation of the SDK.

The last thing to comment on here is that there is also a Shutdown method on the Bootstrap class. I’m not sure exactly when you’d want to call this within a WinForms/WPF application but if you want to be tidy, I guess you should call this in the Application.Exit event.

Window Handle and AppWindow

The other APIs that you’re probably going to want to use are those for retrieving the hWnd (the Window handle) for your application window and how to use that to access the AppWindow (more on using the AppWindow in a subsequent post).

hWnd

If you’re building a WinUI application, retrieving the hWnd for a Window can be done via the WinRT interop api.

IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);

For a WinForms/WPF application you can use the WindowInteropHelper class.

var hWnd = new WindowInteropHelper(this).EnsureHandle();

You might be asking why you need access to the hWnd and you’d be right to challenge this – the fact that we’re back to having to know and use the hWnd for the application window is simply cringeworthy. My take on this is that this is a transient thing and that eventually the team will clean up the API surface to obfuscate the need to access the hWnd . In the short term you’ll need the hWnd for things like displaying some of the WinRT pickers (eg FileSavePicker).

AppWindow

Now that you have the hWnd for the window of your application, you may want to retrieve an AppWindow instance. The AppWindow is the entry point for the new windowing api included in the Windows App SDK – more on this in a subsequent post. For this post, I just want to cover off how you can access the AppWindow instance.

This used to again require an interop method call eg

DO NOT USE THIS CODE
[DllImport("Microsoft.Internal.FrameworkUdk.dll", EntryPoint = "Windowing_GetWindowIdFromWindow", CharSet = CharSet.Unicode)]
public static extern IntPtr GetWindowIdFromWindowHandle(IntPtr hwnd, out WindowId result);

If you were using this interop method in preview1 and are running into issues, the EntryPoint has changed from Windowing_GetWindowIdFromWindowHandle to just Windowing_GetWindowIdFromWindow. However, you don’t even need to define your own interop methods as the SDK includes .NET projections for this too via the Windows.UI.Win32Interop class. You might still want to define a simple extension method for retrieving the AppWindow for the current Window (WinUI).

public static class AppWindowExtensions
{
    public static AppWindow GetAppWindow(this Window window)
    {
        IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
        WindowId myWndId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
        return AppWindow.GetFromWindowId(myWndId);
    }
}

If you’re using this in a WinForms/WPF application, you just need to change the way the hWnd is accessed (see earlier code).

Hopefully this gives you a quick reference on how to get started accessing the Windows App Sdk (preview2) from different app types.