diff --git a/docs/interop.md b/docs/interop.md index ad28cad82..0fe181df1 100644 --- a/docs/interop.md +++ b/docs/interop.md @@ -95,7 +95,28 @@ SetString(MarshalString.GetAbi(marshalStr)); ``` #### Interop Interfaces -The CLR still supports marshaling COM (IUnknown), but not WinRT (IInspectable), interop interfaces. The Windows SDK projection provides definitions for several COM interop interfaces, including ***Windows.Storage.Streams.IBufferByteAccess***, ***WinRT.Interop.IWindowNative***, and ***WinRT.Interop.IInitializeWithWindow***. The Windows SDK projection also provides wrappers for all WinRT interop interfaces included in the Universal API Contract, such as ***Windows.Security.Credentials.UI.UserConsentVerifierInterop***. For custom or extension SDK interop interfaces, C#/WinRT supports two marshaling techniques. +The CLR still supports marshaling COM (IUnknown), but not WinRT (IInspectable), interop interfaces. The Windows SDK projection provides several interop interface helpers for common scenarios. For custom or extension SDK interop interfaces, C#/WinRT supports two marshaling techniques. + +##### Windows SDK + +The Windows SDK projection provides wrappers for common COM interop interfaces, such as ***Windows.Storage.Streams.IBufferByteAccess***, ***WinRT.Interop.IWindowNative***, and ***WinRT.Interop.IInitializeWithWindow***. + +The following sample demonstrates creating a folder picker with an owning window: + +```csharp +var window = new Microsoft.UI.Xaml.Window(); +// ... +var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window); +var folderPicker = new Windows.Storage.Pickers.FolderPicker(); +folderPicker.FileTypeFilter.Add("*"); +WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, hwnd); +var folder = await folderPicker.PickSingleFolderAsync(); +``` + +The Windows SDK projection also provides wrappers for all WinRT interop interfaces included in the Universal API Contract, such as ***Windows.Security.Credentials.UI.UserConsentVerifierInterop*** + +For more info, see: +[Call WinRT COM interop interfaces from .NET 5+ apps](https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/winrt-com-interop-csharp) ##### Projected If possible, the interop interface should be defined in IDL and a C#/WinRT projection produced for it. This automatically generates all marshaling logic so that calling code can pass and receive projected types. This definition of `IUserConsentVerifierInterop` from one of our test components is an example of this: diff --git a/src/WinRT.Runtime/ExceptionHelpers.cs b/src/WinRT.Runtime/ExceptionHelpers.cs index f796948cd..395373253 100644 --- a/src/WinRT.Runtime/ExceptionHelpers.cs +++ b/src/WinRT.Runtime/ExceptionHelpers.cs @@ -20,6 +20,7 @@ public static class ExceptionHelpers internal const int E_LAYOUTCYCLE = unchecked((int)0x802B0014); internal const int E_ELEMENTNOTENABLED = unchecked((int)0x802B001E); internal const int E_ELEMENTNOTAVAILABLE = unchecked((int)0x802B001F); + internal const int ERROR_INVALID_WINDOW_HANDLE = unchecked((int)0x80070578); [DllImport("oleaut32.dll")] private static extern int SetErrorInfo(uint dwReserved, IntPtr perrinfo); @@ -154,6 +155,13 @@ private static Exception GetExceptionForHR(int hr, bool useGlobalErrorState, out case E_ELEMENTNOTENABLED: ex = new Microsoft.UI.Xaml.Automation.ElementNotEnabledException(); break; + case ERROR_INVALID_WINDOW_HANDLE: + ex = new System.Runtime.InteropServices.COMException( +@"Invalid window handle. (0x80070578) +Consider WindowNative, InitializeWithWindow +See https://aka.ms/cswinrt/interop#windows-sdk", + ERROR_INVALID_WINDOW_HANDLE); + break; default: ex = Marshal.GetExceptionForHR(hr, iErrorInfo?.ThisPtr ?? (IntPtr)(-1)); break;