Call interop APIs from a .NET app

As a C# desktop application developer, in .NET you can make use of C# interop classes that represent several interoperability functions and Windows Runtime (WinRT) COM interoperability interfaces. These include C# classes representing IWindowNative, IInitializeWithWindow, the GetWindowIdFromWindow function, and many others.

This topic lists the available C# interop classes, and shows how to use them. The Background section at the end of the topic describes how interop interfaces were used in previous versions of .NET, and why the change was made.

Configure a .NET desktop project to use the C# interop classes

The C# interop classes listed in the next section (Available C# interop classes) are available in .NET either as part of the Windows App SDK, or else by using a particular Target Framework Moniker, as we'll see.

In a WinUI 3 C# desktop project

When you create a new WinUI 3 project in Visual Studio (see Create your first WinUI 3 project), your project is already configured, and you can start using all of the C# interop classes right away.

In other C# desktop project types (WPF or WinForms)

For other .NET desktop project types—such as Windows Presentation Foundation (WPF) or Windows Forms (WinForms)—you'll need to configure your project before you can access the C# interop classes. For the first set of classes listed below, you'll need to reference the Windows App SDK. For the second set, you'll need to configure a Target Framework Moniker that targets Windows 10, version 1809 or later, like this:

  1. Open the project file for your C# .NET desktop project.

  2. In the .csproj file, modify the TargetFramework element to target a specific .NET and Windows SDK version. For example, the following element is appropriate for a .NET 6 project that targets Windows 10, version 2004.

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

For more information—including a list of other supported values—see Use the Target Framework Moniker option.

Available C# interop classes

Note

The classes below require the .NET 6 SDK or later.

Here are the available C# interop classes, mapped from their underlying interop function or WinRT COM interop interface. Each class listed implements the function/methods of its underlying interop API, and provides type-safe wrappers for parameters and return values. For example, Windows.ApplicationModel.DataTransfer.DragDrop.Core.DragDropManagerInterop.GetForWindow requires an IntPtr window handle (HWND) parameter, and returns a CoreDragDropManager object. All of the C# interop classes below and associated methods are static.

Available as part of the Windows App SDK

The Microsoft.UI.Win32Interop class implements the C# interop methods in the table below. For a code example, see Manage app windows.

Interop function C# interop method
GetDisplayIdFromMonitor (Microsoft.UI) DisplayId Win32Interop.GetDisplayIdFromMonitor(IntPtr hmonitor)
GetIconFromIconId (Microsoft.UI) IntPtr Win32Interop.GetIconFromIconId(IconId iconId)
GetIconIdFromIcon (Microsoft.UI) IconId Win32Interop.GetIconIdFromIcon(IntPtr hicon)
GetMonitorFromDisplayId (Microsoft.UI) IntPtr Win32Interop.GetMonitorFromDisplayId(DisplayId displayId)
GetWindowFromWindowId (Microsoft.UI) IntPtr Win32Interop.GetWindowFromWindowId(WindowId windowId)
GetWindowIdFromWindow (Microsoft.UI) WindowId Win32Interop.GetWindowIdFromWindow(IntPtr hwnd)

Available via Target Framework Moniker

WinRT COM interop interface C# interop class
IAccountsSettingsPaneInterop (Windows.UI.ApplicationSettings) AccountsSettingsPaneInterop
IDisplayInformationStaticsInterop Introduced with TFM net6.0-windows10.0.22621.0 and .NET 6.0.7.

(Windows.Graphics.Display) DisplayInformationInterop
IDragDropManagerInterop (Windows.ApplicationModel.DataTransfer.DragDrop.Core) DragDropManagerInterop
IInitializeWithWindow (WinRT.Interop) InitializeWithWindow
IInputPaneInterop (Windows.UI.ViewManagement) InputPaneInterop
IPlayToManagerInterop (Windows.Media.PlayTo) PlayToManagerInterop
IPrintManagerInterop (Windows.Graphics.Printing) PrintManagerInterop
IRadialControllerConfigurationInterop (Windows.UI.Input) RadialControllerConfigurationInterop
IRadialControllerIndependentInputSourceInterop (Windows.UI.Input.Core) RadialControllerIndependentInputSourceInterop
IRadialControllerInterop (Windows.UI.Input) RadialControllerInterop
ISpatialInteractionManagerInterop (Windows.UI.Input.Spatial) SpatialInteractionManagerInterop
ISystemMediaTransportControlsInterop (Windows.Media) SystemMediaTransportControlsInterop
IUIViewSettingsInterop (Windows.UI.ViewManagement) UIViewSettingsInterop
IUserConsentVerifierInterop (Windows.Security.Credentials.UI) UserConsentVerifierInterop
IWebAuthenticationCoreManagerInterop (Windows.Security.Authentication.Web.Core) WebAuthenticationCoreManagerInterop
IWindowNative WinUI 3 only

(WinRT.Interop) WindowNative

For alternatives for WPF and WinForms, see Retrieve a window handle (HWND).

Code example

This code example demonstrates how to use two of the C# interop classes in a WinUI 3 application (see Create your first WinUI 3 project). The example scenario is to display a Windows.Storage.Pickers.FolderPicker. But before displaying the picker in a desktop app, it's necessary to initialize it with the handle (HWND) of the owner window.

  1. You can obtain a window handle (HWND) by using the IWindowNative WinRT COM interop interface. And (looking in the table in the previous section) that interface is represented by the WinRT.Interop.WindowNative C# interop class. Here, the this object is a reference to a Microsoft.UI.Xaml.Window object from the main window code-behind file.
  2. To initialize a piece of UI with an owner window, you use the IInitializeWithWindow WinRT COM interop interface. And that interface is represented by the WinRT.Interop.InitializeWithWindow C# interop class.
private async void myButton_Click(object sender, RoutedEventArgs e)
{
    // Create a folder picker.
    var folderPicker = new Windows.Storage.Pickers.FolderPicker();

    // 1. Retrieve the window handle (HWND) of the current WinUI 3 window.
    var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);

    // 2. Initialize the folder picker with the window handle (HWND).
    WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, hWnd);

    // Use the folder picker as usual.
    folderPicker.FileTypeFilter.Add("*");
    var folder = await folderPicker.PickSingleFolderAsync();
}

Also see Retrieve a window handle (HWND) and Display WinRT UI objects that depend on CoreWindow.

Background

Previous versions of the .NET Framework and .NET Core had built-in knowledge of WinRT. With those previous versions, you could define an interop interface directly in C# with the ComImport attribute, and then directly cast a projected class to that interop interface.

Since WinRT is a Windows-specific technology, to support the portability and efficiency goals of .NET, we lifted the WinRT projection support out of the C# compiler and .NET runtime, and moved it into the C#/WinRT toolkit (see Built-in support for WinRT is removed from .NET).

While the ComImport technique still works for IUnknown-based interop interfaces, it no longer works for the IInspectable-based interfaces that are used for interoperating with WinRT.

So as a replacement, in .NET, you can make use of the C# interop classes described in this topic.

Troubleshooting and known issues

There are currently no known issues for the C# interop classes. To provide feedback, or to report other issues, add your feedback to an existing issue, or file a new issue on the WindowsAppSDK GitHub repo.