C#/WinRT

C#/WinRT is a NuGet-packaged toolkit that provides Windows Runtime (WinRT) projection support for the C# language. A projection is a translation layer, such as an interop assembly, that enables programming WinRT APIs in a natural and familiar way for the target language. For example, 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 types, and the latest version enables you to create and reference WinRT interop assemblies. Future releases of C#/WinRT will add support for authoring WinRT types in C#.

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

Motivation for C#/WinRT

.NET Core is the focus for the .NET platform, and .NET 5 is the latest major release. It 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 5, we lifted the WinRT projection support out of the .NET compiler and runtime and moved it into the C#/WinRT toolkit. 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 WinUI 3.0. This release of WinUI lifts native Microsoft UI controls and features out of the operating system. This enables app developers to use the latest controls and visuals on Windows 10, version 1803, 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.

Create 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 Windows Metadata files and generate .NET 5.0 C# code. You can compile these source files to interop assemblies, similar to how C++/WinRT generates headers for C++ language projection. You can then distribute the C#/WinRT interop assemblies for applications to reference, along with the C#/WinRT runtime assembly.

For a walkthrough that demonstrates how to create and distribute an interop assembly as a NuGet package, see Walkthrough: Generate a .NET 5 projection from a C++/WinRT component and update the NuGet.

Invoke cswinrt.exe

To invoke cswinrt.exe from a project, install the latest C#/WinRT NuGet package. You can then set C#/WinRT-specific project properties in a C# Class Library (.NET Core) project to generate an interop assembly. The following project fragment demonstrates a simple invocation of cswinrt to generate projection sources for types in the Contoso namespace. These sources are then included in the project build.

<PropertyGroup>
  <CsWinRTIncludes>Contoso</CsWinRTIncludes>
</PropertyGroup>

In this project you would also need to reference the CsWinRT NuGet package and the project-specific .winmd files you want to project, whether through a NuGet package, project reference or direct reference. By default, the Windows and Microsoft namespaces are not projected. For a full list of CsWinRT project properties, refer to the CsWinRT NuGet documentation.

Distribute the interop assembly

An interop assembly is typically distributed as a NuGet package, along with a dependency on the C#/WinRT NuGet package for the required C#/WinRT runtime assembly, WinRT.Runtime.dll.

To ensure that the correct version of the C#/WinRT runtime is deployed for .NET 5.0 applications, include a targetFramework condition in the .nuspec file with a dependency on the C#/WinRT NuGet package.

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
  <metadata>
    <dependencies>
      <group targetFramework="net5.0">
        <dependency id="Microsoft.Windows.CsWinRT" version="1.0.1" />
      </group>
    </dependencies>
  </metadata>
</package>

Note

The target framework moniker for .NET 5.0 is moving from ".NETCoreApp5.0" to "net5.0".

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.

To consume projected C#/WinRT types, add a reference to the appropriate C#/WinRT interop NuGet package to your project. This causes both the interop assembly and the C#/WinRT runtime assembly to be added to the project.

If you distribute a third-party WinRT component without an official interop assembly, an application project may follow the procedure for creating 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.

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, available in Windows 10 version 1903 and later. This may also require use of the VCRT Forwarders package, if the component was built to target UWP apps.

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>
    
  • 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>net5.0-windows10.0.19041.0</TargetFramework>
    

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

.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 5 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