diff --git a/Microsoft.Toolkit.Uwp.Notifications/DesktopNotificationManager/DesktopNotificationManagerCompat.cs b/Microsoft.Toolkit.Uwp.Notifications/DesktopNotificationManager/DesktopNotificationManagerCompat.cs index 89cecae17eb..f70be4537fb 100644 --- a/Microsoft.Toolkit.Uwp.Notifications/DesktopNotificationManager/DesktopNotificationManagerCompat.cs +++ b/Microsoft.Toolkit.Uwp.Notifications/DesktopNotificationManager/DesktopNotificationManagerCompat.cs @@ -3,13 +3,11 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections; -using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using System.Runtime.InteropServices; using System.Text; using Windows.UI.Notifications; +using static Microsoft.Toolkit.Uwp.Notifications.NotificationActivator; namespace Microsoft.Toolkit.Uwp.Notifications { @@ -23,12 +21,19 @@ public class DesktopNotificationManagerCompat /// public const string ToastActivatedLaunchArg = "-ToastActivated"; + private const int CLASS_E_NOAGGREGATION = -2147221232; + private const int E_NOINTERFACE = -2147467262; + private const int CLSCTX_LOCAL_SERVER = 4; + private const int REGCLS_MULTIPLEUSE = 1; + private const int S_OK = 0; + private static readonly Guid IUnknownGuid = new Guid("00000000-0000-0000-C000-000000000046"); + private static bool _registeredAumidAndComServer; private static string _aumid; private static bool _registeredActivator; /// - /// If not running under the Desktop Bridge, you must call this method to register your AUMID with the Compat library and to + /// If you're not using MSIX or sparse packages, you must call this method to register your AUMID with the Compat library and to /// register your COM CLSID and EXE in LocalServer32 registry. Feel free to call this regardless, and we will no-op if running /// under Desktop Bridge. Call this upon application startup, before calling any other APIs. /// @@ -73,24 +78,85 @@ private static void RegisterComServer(string exePath) key.SetValue(null, '"' + exePath + '"' + " " + ToastActivatedLaunchArg); } + /* + * RegisterActivator code and all internal dependencies is from FrecherxDachs. + * See entry #2 in ThirdPartyNotices.txt in root repository directory for full license. */ + /// /// Registers the activator type as a COM server client so that Windows can launch your activator. /// /// Your implementation of NotificationActivator. Must have GUID and ComVisible attributes on class. public static void RegisterActivator() - where T : NotificationActivator + where T : NotificationActivator, new() { - // Register type - var regService = new RegistrationServices(); - - regService.RegisterTypeForComClients( - typeof(T), - RegistrationClassContext.LocalServer, - RegistrationConnectionType.MultipleUse); + // Big thanks to FrecherxDachs for figuring out the following code which works in .NET Core 3: https://github.com/FrecherxDachs/UwpNotificationNetCoreTest + var uuid = typeof(T).GUID; + uint cookie; + CoRegisterClassObject( + uuid, + new NotificationActivatorClassFactory(), + CLSCTX_LOCAL_SERVER, + REGCLS_MULTIPLEUSE, + out cookie); _registeredActivator = true; } + [ComImport] + [Guid("00000001-0000-0000-C000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IClassFactory + { + [PreserveSig] + int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject); + + [PreserveSig] + int LockServer(bool fLock); + } + + private class NotificationActivatorClassFactory : IClassFactory + where T : NotificationActivator, new() + { + public int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject) + { + ppvObject = IntPtr.Zero; + + if (pUnkOuter != IntPtr.Zero) + { + Marshal.ThrowExceptionForHR(CLASS_E_NOAGGREGATION); + } + + if (riid == typeof(T).GUID || riid == IUnknownGuid) + { + // Create the instance of the .NET object + ppvObject = Marshal.GetComInterfaceForObject( + new T(), + typeof(INotificationActivationCallback)); + } + else + { + // The object that ppvObject points to does not support the + // interface identified by riid. + Marshal.ThrowExceptionForHR(E_NOINTERFACE); + } + + return S_OK; + } + + public int LockServer(bool fLock) + { + return S_OK; + } + } + + [DllImport("ole32.dll")] + private static extern int CoRegisterClassObject( + [MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, + [MarshalAs(UnmanagedType.IUnknown)] object pUnk, + uint dwClsContext, + uint flags, + out uint lpdwRegister); + /// /// Creates a toast notifier. You must have called first (and also if you're a classic Win32 app), or this will throw an exception. /// @@ -151,7 +217,7 @@ private static void EnsureRegistered() } /// - /// Gets a value indicating whether http images can be used within toasts. This is true if running under Desktop Bridge. + /// Gets a value indicating whether http images can be used within toasts. This is true if running with package identity (MSIX or sparse package). /// public static bool CanUseHttpImages { @@ -206,4 +272,4 @@ private static bool IsWindows7OrLower } } } -} \ No newline at end of file +} diff --git a/Microsoft.Toolkit.Uwp.Notifications/Microsoft.Toolkit.Uwp.Notifications.csproj b/Microsoft.Toolkit.Uwp.Notifications/Microsoft.Toolkit.Uwp.Notifications.csproj index 0b2cf702e3a..9ceccd958ec 100644 --- a/Microsoft.Toolkit.Uwp.Notifications/Microsoft.Toolkit.Uwp.Notifications.csproj +++ b/Microsoft.Toolkit.Uwp.Notifications/Microsoft.Toolkit.Uwp.Notifications.csproj @@ -1,7 +1,7 @@  - netstandard1.4;uap10.0;native;net461 + netstandard1.4;uap10.0;native;net461;netcoreapp3.0 $(DefineConstants);NETFX_CORE Windows Community Toolkit Notifications @@ -14,6 +14,35 @@ notifications win10 windows 10 tile tiles toast toasts badge xml uwp c# csharp c++ true + + + + + + + + + + + + $(DefineConstants);WINDOWS_UWP + + + + + + + + + + + + + + + + + @@ -27,20 +56,6 @@ - - - - - - - - - $(MSBuildProgramFiles32)\Windows Kits\10\UnionMetadata\$(TargetPlatformVersion)\Windows.winmd - true - False - - - winmdobj UAP diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index 4d874d686c1..128e038252e 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -6,6 +6,7 @@ Do Not Translate or Localize This project incorporates components from the projects listed below. The original copyright notices and the licenses under which the .NET Foundation received such components are set forth below. The .NET Foundation reserves all rights not expressly granted herein, whether by implication, estoppel or otherwise. 1. PedroLamas/DeferredEvents version 1.0.4 (https://github.com/PedroLamas/DeferredEvents) +2. MichaeIDietrich/UwpNotificationNetCoreTest commit 5c1a4a3 (https://github.com/MichaeIDietrich/UwpNotificationNetCoreTest), used in DesktopNotificationManagerCompat.cs to support .NET Core 3.0. %% PedroLamas/DeferredEvents NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -30,3 +31,29 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= END OF PedroLamas/DeferredEvents NOTICES AND INFORMATION + +%% MichaeIDietrich/UwpNotificationNetCoreTest NOTICES AND INFORMATION BEGIN HERE +========================================= +The MIT License (MIT) + +Copyright (c) 2020 Michael Dietrich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +========================================= +END OF FrecherxDachs/UwpNotificationNetCoreTest NOTICES AND INFORMATION