C#/WinRT

C#/WinRT is a NuGet-packaged toolkit that provides Windows Runtime (WinRT) projection support for the C# language. A projection assembly is an interop assembly, which enables programming WinRT APIs in a natural and familiar way for the target language. The C#/WinRT projection hides the details of interop between C# and WinRT interfaces, and provides mappings of many WinRT types to appropriate .NET equivalents, such as strings, URIs, common value types, and generic collections.

C#/WinRT currently provides support for consuming WinRT APIs through the use of Target Framework Monikers (TFMs) in .NET. Setting the TFM with a specific Windows SDK version adds references to the Windows SDK projection and runtime assemblies generated by C#/WinRT.

The C#/WinRT NuGet package enables you to create and reference your own WinRT interop assemblies for .NET consumers. The latest C#/WinRT version also includes a preview of authoring WinRT types in C#.

For additional information, see the C#/WinRT GitHub repo.

Motivation for C#/WinRT

.NET (previously known as .NET Core) is an open-source, cross-platform runtime that can be used to build device, cloud, and IoT applications.

Previous versions of .NET Framework and .NET Core had built-in knowledge of WinRT—a Windows-specific technology. To support the portability and efficiency goals of .NET 6+, we lifted the WinRT projection support out of the .NET compiler and runtime and moved it into the C#/WinRT toolkit (see Built-in support for WinRT is removed from .NET). The goal of C#/WinRT is to provide parity with the built-in WinRT support provided by earlier versions of the C# compiler and .NET runtime. For details, see .NET mappings of Windows Runtime types.

C#/WinRT also supports components in the Windows App SDK, including WinUI 3. The Windows App SDK lifts native Microsoft UI controls and other native components out of the operating system. This enables app developers to use the latest controls and components on Windows 10, version 1809, and later releases.

Finally, C#/WinRT is a general toolkit and is intended to support other scenarios where built-in support for WinRT is not available in the C# compiler or .NET runtime.

What's new

The latest C#/WinRT releases can be found on our release notes page in the Github repo.

Usage

The C#/WinRT NuGet package can be used to both generate C# projections (also called interop assemblies) from WinRT components and in Authoring C#/WinRT components. For more details regarding the usage scenarios for C#/WinRT, refer to the usage guide on our repo.

Generate and distribute an interop assembly

WinRT APIs are defined in Windows Metadata (WinMD) files. The C#/WinRT NuGet package (Microsoft.Windows.CsWinRT) includes the C#/WinRT compiler, cswinrt.exe, which you can use to process WinMD files and generate .NET C# code. C#/WinRT compiles these source files into an interop assembly, similar to how C++/WinRT generates headers for the C++ language projection. You can then distribute the C#/WinRT interop assembly along with the implementation assembly for .NET applications to reference, typically as a NuGet package.

For more details on how to generate and distribute an interop assembly, see Generate a C# projection from a C++/WinRT component, distribute as a NuGet for .NET apps.

Reference an interop assembly

Typically, C#/WinRT interop assemblies are referenced by application projects. But they may also be referenced in turn by intermediate interop assemblies. For example, the WinUI interop assembly would reference the Windows SDK interop assembly.

If you distribute a third-party WinRT component without an official interop assembly, an application project may follow the procedure for generating an interop assembly to generate its own private projection sources. We don't recommend this approach, because it can produce conflicting projections of the same type within a process. NuGet packaging, following the Semantic Versioning scheme, is designed to prevent this. An official third-party interop assembly is preferred.

Embedded support for WinRT types (Preview)

Starting with C#/WinRT version 1.4.1, support is included for embedding Windows SDK projection and runtime sources for both .NET and .NET Standard 2.0 into your library or app's output. This is useful in cases where usage of Windows SDK types is self-contained. Embedded support removes dependencies on WinRT.Runtime.dll and Microsoft.Windows.SDK.NET.dll which reduces the library or app output size. It also allows library developers to provide downlevel support and removes the need for multi-targeting.

For more details, see the C#/WinRT embedded documentation on our repo.

WinRT type activation

C#/WinRT supports activation of WinRT types hosted by the operating system, as well as third-party components such as Win2D. Support for third-party component activation in a desktop application is enabled with registration free WinRT activation (see Enhancing Non-packaged Desktop Apps using Windows Runtime Components), available in Windows 10, version 1903 and later. Native C++ components should set the Windows Desktop Compatible property to True either via the project properties or the .vcxproj file, in order to reference and forward the Microsoft.VCLibs.Desktop binaries to consuming apps. Otherwise, the VCRT Forwarders package will be required by consuming apps if the component targets UWP apps only.

C#/WinRT also provides an activation fallback path if Windows fails to activate the type as described above. In this case, C#/WinRT attempts to locate a native implementation DLL based on the fully qualified type name, progressively removing elements. For example, the fallback logic would attempt to activate the Contoso.Controls.Widget type from the following modules, in sequence:

  1. Contoso.Controls.Widget.dll
  2. Contoso.Controls.dll
  3. Contoso.dll

C#/WinRT uses the LoadLibrary alternate search order to locate an implementation DLL. An app relying on this fallback behavior should package the implementation DLL alongside the app module.

Common errors and troubleshooting

  • Error: "Windows Metadata not provided or detected."

    You can specify Windows Metadata by using the <CsWinRTWindowsMetadata> project property, for example:

    <CsWinRTWindowsMetadata>10.0.19041.0</CsWinRTWindowsMetadata>
    

    In C#/WinRT version 1.2.1 and later, this property defaults to TargetPlatformVersion, which is derived from the Windows SDK version specified in the TargetFramework property.

  • Error CS0246: The type or namespace name 'Windows' could not be found (are you missing a using directive or an assembly reference?)

    To address this error, edit your <TargetFramework> property to target a specific Windows version, for example:

    <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
    

    Refer to the docs on Calling Windows Runtime APIs for more details on specifying the <TargetFramework> property.

  • System.InvalidCastException when casting to an interface that has the ComImport attribute

    When casting an object to an interface that has the ComImport attribute, you'll need to use the .As<> operator instead of using an explicit cast expression. For example:

    someObject.As<SomeComImportInterface>
    

    For more details, see the COM interop guide.

  • System.Runtime.InteropServices.COMException: Class not registered (0x80040154 (REGDB_E_CLASSNOTREG))

    • If you see this exception when consuming a C#/WinRT projection from a C++/WinRT component, make sure the component has set the Windows Desktop Compatible property to True either via the project properties or via the .vcxproj file.

.NET SDK versioning errors

You may encounter the following errors or warnings in a project that is built with an earlier .NET SDK version than any of its dependencies.

Error or warning message Reason
Warning MSB3277: Found conflicts between different versions of WinRT.Runtime or Microsoft.Windows.SDK.NET that could not be resolved. This build warning occurs when referencing a library that exposes Windows SDK types on its API surface.
Error CS1705: Assembly 'AssemblyName1' uses 'TypeName' which has a higher version than referenced assembly 'AssemblyName2' This build compiler error occurs when referencing and consuming exposed Windows SDK types in a library.
System.IO.FileLoadException This runtime error may occur when calling certain APIs in a library that does not expose Windows SDK types.

To fix these errors, update your .NET SDK to the latest version. Doing so will ensure that the runtime and Windows SDK assembly versions used by your application are compatible with all dependencies. These errors may occur with early servicing/feature updates to the .NET SDK, because runtime fixes may require updates to our assembly versions.

Known issues

Known issues and breaking changes are noted in the C#/WinRT GitHub repo.

If you encounter any functional issues with the C#/WinRT NuGet package, the cswinrt.exe compiler, or the generated projection sources, submit issues to us via the C#/WinRT issues page.

Additional resources