Use the Windows App SDK runtime for apps packaged with external location or unpackaged

Note

If your app is installed by using MSIX technology, then see Windows App SDK deployment guide for framework-dependent packaged apps.

If your app isn't installed by using MSIX (that is, it's packaged with external location or unpackaged), then you must initialize the Windows App SDK for use before you can call Windows App SDK features such as WinUI 3, App Lifecycle, MRT Core, and DWriteCore. Your app must initialize the Windows App SDK runtime before using any other feature of the Windows App SDK.

  • Beginning in Windows App SDK 1.0, that can be done automatically when your app starts via auto-initialization (set the project property <WindowsPackageType>None</WindowsPackageType>). For a demonstration, see Create your first WinUI 3 project.
  • But if you have advanced needs (such as handling errors by showing your own custom UI or logging, or if you need to load a version of the Windows App SDK that's different from the version you built with), then continue reading this topic. In those scenarios, instead of auto-initialization, you can call the bootstrapper API explicitly.

Either of the two techniques above allows an app that doesn't use MSIX to take a dynamic dependency on the Windows App SDK at run time.

For background information about dynamic dependencies, see MSIX framework packages and dynamic dependencies.

Behind the scenes, and opting out of automatic module initialization

The code generated by the WindowsPackageType property mentioned above leverages module initializers to call the bootstrapper API. The bootstrapper does the heavy lifting to find the Windows App SDK and enable the current process to use it. The generated code handles both initialization and shutdown. You can control initialization's behavior with the following project properties:

  • <WindowsAppSDKBootstrapAutoInitializeOptions_Default>true</WindowsAppSDKBootstrapAutoInitializeOptions_Default>
    • Use default options.
  • <WindowsAppSDKBootstrapAutoInitializeOptions_None>true</WindowsAppSDKBootstrapAutoInitializeOptions_None>
    • Use no options.
  • <WindowsAppSDKBootstrapAutoInitializeOptions_OnError_DebugBreak>true</WindowsAppSDKBootstrapAutoInitializeOptions_OnError_DebugBreak>
  • <WindowsAppSDKBootstrapAutoInitializeOptions_OnError_DebugBreak_IfDebuggerAttached>true</WindowsAppSDKBootstrapAutoInitializeOptions_OnError_DebugBreak_IfDebuggerAttached>
    • Call DebugBreak() if an error occurs only if a debugger is attached to the process.
  • <WindowsAppSDKBootstrapAutoInitializeOptions_OnError_FailFast>true</WindowsAppSDKBootstrapAutoInitializeOptions_OnError_FailFast>
    • Perform a fail-fast if an error occurs.
  • <WindowsAppSDKBootstrapAutoInitializeOptions_OnNoMatch_ShowUI>true</WindowsAppSDKBootstrapAutoInitializeOptions_OnNoMatch_ShowUI>
    • Prompt the user to acquire the Windows App SDK runtime if a matching one cannot be found.
  • <WindowsAppSDKBootstrapAutoInitializeOptions_OnPackageIdentity_NoOp>true</WindowsAppSDKBootstrapAutoInitializeOptions_OnPackageIdentity_NoOp>
    • Succceed if called in a process with package identity (otherwise it fails and an error is returned).

If you want your app to have explicit control, then you can directly call the boostrapper API early in your application's startup. In that case you don't need WindowsPackageType in your project file.

Note

In addition to the automatic initialization and the bootstrapper API, the Windows App SDK also provides an implementation of the dynamic dependency API. This API enables your unpackaged apps to take a dependency on any framework package (not just the Windows App SDK framework package), and it is used internally by the bootstrapper API. For more information about the dynamic dependency API, see Use the dynamic dependency API to reference MSIX packages at run time.

Opting out of (or into) automatic module initialization

The project property <WindowsAppSdkBootstrapInitialize>false</WindowsAppSdkBootstrapInitialize> disables the automatic module initialization described above (the bootstrapper API isn't called). That allows your app to take responsibility and directly call the bootstrapper API.

As of version 1.2 of the Windows App SDK (from the stable channel), automatic module initialization applies only to projects that produce an executable (that is, the OutputType project property is set to Exe or WinExe). This is to prevent adding auto-initializers into class library DLLs and other non-executables by default. If you do need an auto-initializer in a non-executable (for example, a test DLL loaded by a host process executable that doesn't initialize the bootstrapper), then you can explicitly enable an auto-initializer in your project with <WindowsAppSdkBootstrapInitialize>true</WindowsAppSdkBootstrapInitialize>.

Using the bootstrapper API

Important

The MddBootstrapInitialize2 function mentioned below is available starting in version 1.1.

The bootstrapper API consists of three C/C++ functions that are declared in the mddbootstrap.h header file in the Windows App SDK: MddBootstrapInitialize, MddBootstrapInitialize2, and MddBootstrapShutdown. Those functions are provided by the bootstrapper library in the Windows App SDK. That library is a small DLL that you must distribute with your app; it's not part of the framework package itself.

MddBootstrapInitialize2

This function initializes the calling process to use the version of the Windows App SDK framework package that best matches the criteria that you pass to the function parameters. Typically, that results in referencing the version of the framework package that matches the Windows App SDK NuGet package that's installed. If multiple packages meet the criteria, then the best candidate is selected. This function must be one of the first calls in the app's startup to ensure the bootstrapper component can properly initialize the Windows App SDK and add the run-time reference to the framework package.

The bootstrapper API uses the Dynamic Dependencies API to add the Windows App SDK runtime's framework package to the current process's package graph and otherwise enable access to the package.

This function also initializes the Dynamic Dependency Lifetime Manager (DDLM). That component provides infrastructure to prevent the OS from servicing the Windows App SDK framework package while it's being used by an unpackaged app.

MddBootstrapShutdown

This function removes the changes to the current process that were made by a call to MddBootstrapInitialize. After this function is called, your app can no longer call Windows App SDK APIs, including the dynamic dependencies API.

This function also shuts down the Dynamic Dependency Lifetime Manager (DDLM) so that Windows can service the framework package as necessary.

.NET wrapper for the bootstrapper API

Although you can call the C/C++ bootstrapper API directly from .NET apps, that requires the use of platform invoke to call the functions. In Windows App SDK 1.0 and later releases, a .NET wrapper for the bootstrapper API is available in the Microsoft.WindowsAppRuntime.Bootstrap.Net.dll assembly. That assembly provides an easier and more natural API for .NET developers to access the bootstrapper's functionality. The Bootstrap class provides static Initialize, TryInitialize, and Shutdown functions that wrap calls to the MddBootstrapInitialize and MddBootstrapShutdown functions for most common scenarios. For an example that demonstrates how to use the .NET wrapper for the bootstrapper API, see the C# instructions in Tutorial: Use the bootstrapper API in an app packaged with external location or unpackaged that uses the Windows App SDK.

For more information about the .NET wrapper for the bootstrapper API, see these resources:

C++ wrapper for the bootstrapper API

A C++ wrapper for the bootstrapper API is available starting in Windows App SDK 1.1.

See Bootstrapper C++ API.

Declare OS compatibility in your application manifest

To declare operating system (OS) compatibility, and to avoid the Windows App SDK defaulting to Windows 8 behavior (and potential crashes), you can include a side-by-side application manifest with your packaged with external location or unpackaged app. See Application manifests (it's the file that declares things like DPI awareness, and is embedded into your app's .exe during build). This might be an issue if you're adding Windows App SDK support to an existing app, rather than creating a new one via a Visual Studio project template.

If you don't already have a side-by-side application manifest in your project, then add a new XML file to your project, and name it as recommended in Application manifests. Add to the file the compatibility element and the child elements shown in the following example. These values control the quirks level for the components running in your app's process.

Replace the Id attribute of the maxversiontested element with the version number of Windows that you're targeting (must be 10.0.17763.0 or a later release). Note that setting a higher value means that older versions of Windows won't run your app properly because every Windows release knows only of versions before it. So if you want your app to run on Windows 10, version 1809 (10.0; Build 17763), then you should either leave the 10.0.17763.0 value as is, or add multiple maxversiontested elements for the different values that your app supports.

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
        <application>
            <!-- Windows 10, version 1809 (10.0; Build 17763) -->
            <maxversiontested Id="10.0.17763.0"/>
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
        </application>
    </compatibility>
</assembly>