This commit is contained in:
Andrew Leader 2020-08-20 19:03:44 -07:00
Родитель 1518f2820a
Коммит 236d1e3f4d
12 изменённых файлов: 310 добавлений и 28 удалений

Просмотреть файл

@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -12,6 +13,7 @@ using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using Microsoft.Win32;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Resources;
@ -26,10 +28,35 @@ namespace Microsoft.Toolkit.Uwp.Notifications
/// </summary>
public class DesktopNotificationManagerCompat
{
private static bool _registeredOnActivated;
private static List<OnActivated> _onActivated = new List<OnActivated>();
/// <summary>
/// Event that is triggered when a notification or notification button is clicked.
/// </summary>
public static event OnActivated OnActivated;
public static event OnActivated OnActivated
{
add
{
lock (_onActivated)
{
if (!_registeredOnActivated)
{
// Desktop Bridge apps will dynamically register upon first subscription to event
CreateAndRegisterActivator();
}
_onActivated.Add(value);
}
}
remove
{
lock (_onActivated)
{
_onActivated.Remove(value);
}
}
}
internal static void OnActivatedInternal(string args, Internal.NotificationActivator.NOTIFICATION_USER_INPUT_DATA[] input, string aumid)
{
@ -43,16 +70,21 @@ namespace Microsoft.Toolkit.Uwp.Notifications
}
}
try
var e = new DesktopNotificationActivatedEventArgs()
{
OnActivated?.Invoke(new DesktopNotificationActivatedEventArgs()
{
Argument = args,
UserInput = userInput
});
Argument = args,
UserInput = userInput
};
OnActivated[] listeners;
lock (_onActivated)
{
listeners = _onActivated.ToArray();
}
catch
foreach (var listener in listeners)
{
listener(e);
}
}
@ -69,6 +101,7 @@ namespace Microsoft.Toolkit.Uwp.Notifications
private static readonly Guid IUnknownGuid = new Guid("00000000-0000-0000-C000-000000000046");
private static string _aumid;
private static string _win32Aumid;
static DesktopNotificationManagerCompat()
{
@ -77,25 +110,19 @@ namespace Microsoft.Toolkit.Uwp.Notifications
private static void Initialize()
{
string aumid;
if (DesktopBridgeHelpers.IsRunningAsUwp())
{
aumid = Package.Current.Id.FamilyName;
_aumid = Package.Current.Id.FamilyName;
}
else
{
// Win32 apps are uniquely identified based on their process name
aumid = GetAumidFromCurrentProcess(Process.GetCurrentProcess());
_aumid = GetAumidFromCurrentProcess(Process.GetCurrentProcess());
// Store the AUMID for Win32 apps since it'll be needed later
_aumid = aumid;
_win32Aumid = _aumid;
}
// Create and register activator
var activatorType = CreateActivatorType(aumid);
RegisterActivator(activatorType);
// If running as Desktop Bridge
if (DesktopBridgeHelpers.IsRunningAsUwp())
{
@ -103,6 +130,10 @@ namespace Microsoft.Toolkit.Uwp.Notifications
return;
}
// Create and register activator
var activatorType = CreateActivatorType(_aumid);
RegisterActivator(activatorType);
// Otherwise, register via registry
var currProcess = Process.GetCurrentProcess();
@ -111,7 +142,7 @@ namespace Microsoft.Toolkit.Uwp.Notifications
string iconPath = "C:\\icon.png"; // TODO: Need to grab icon from process name
using (var rootKey = Registry.CurrentUser.CreateSubKey(@"Software\Classes\AppUserModelId\" + aumid))
using (var rootKey = Registry.CurrentUser.CreateSubKey(@"Software\Classes\AppUserModelId\" + _aumid))
{
rootKey.SetValue("DisplayName", displayName);
rootKey.SetValue("IconUri", iconPath);
@ -161,9 +192,20 @@ namespace Microsoft.Toolkit.Uwp.Notifications
parent: typeof(Internal.NotificationActivator),
interfaces: new Type[0]);
string clsid;
if (DesktopBridgeHelpers.IsRunningAsUwp())
{
clsid = GetClsidFromPackageManifest();
}
else
{
clsid = GenerateGuid(aumid);
}
tb.SetCustomAttribute(new CustomAttributeBuilder(
con: typeof(GuidAttribute).GetConstructor(new Type[] { typeof(string) }),
constructorArgs: new object[] { GenerateGuid(aumid) }));
constructorArgs: new object[] { clsid }));
tb.SetCustomAttribute(new CustomAttributeBuilder(
con: typeof(ComVisibleAttribute).GetConstructor(new Type[] { typeof(bool) }),
@ -182,6 +224,43 @@ namespace Microsoft.Toolkit.Uwp.Notifications
return tb.CreateType();
}
private static string GetClsidFromPackageManifest()
{
var appxManifestPath = Path.Combine(Package.Current.InstalledLocation.Path, "AppxManifest.xml");
XmlDocument doc = new XmlDocument();
doc.Load(appxManifestPath);
var namespaceManager = new XmlNamespaceManager(doc.NameTable);
namespaceManager.AddNamespace("default", "http://schemas.microsoft.com/appx/manifest/foundation/windows10");
namespaceManager.AddNamespace("desktop", "http://schemas.microsoft.com/appx/manifest/desktop/windows10");
namespaceManager.AddNamespace("com", "http://schemas.microsoft.com/appx/manifest/com/windows10");
var activatorClsidNode = doc.SelectSingleNode("/default:Package/default:Applications/default:Application[1]/default:Extensions/desktop:Extension[@Category='windows.toastNotificationActivation']/desktop:ToastNotificationActivation/@ToastActivatorCLSID", namespaceManager);
if (activatorClsidNode == null)
{
throw new InvalidOperationException("Your app manifest must have a toastNotificationActivation extension with a valid ToastActivatorCLSID specified.");
}
var clsid = activatorClsidNode.Value;
// Make sure they have a COM class registration matching the CLSID
var comClassNode = doc.SelectSingleNode($"/default:Package/default:Applications/default:Application[1]/default:Extensions/com:Extension[@Category='windows.comServer']/com:ComServer/com:ExeServer/com:Class[@Id='{clsid}']", namespaceManager);
if (comClassNode == null)
{
throw new InvalidOperationException("Your app manifest must have a comServer extension with a class ID matching your toastNotificationActivator's CLSID.");
}
var argumentsNode = comClassNode.ParentNode.Attributes.GetNamedItem("Arguments");
if (argumentsNode == null || argumentsNode.Value != "-ToastActivated")
{
throw new InvalidOperationException("Your arguments on your comServer extension for toast activation must be set exactly to \"-ToastActivated\"");
}
return clsid;
}
/// <summary>
/// From https://stackoverflow.com/a/41622689/1454643
/// Generates Guid based on String. Key assumption for this algorithm is that name is unique (across where it it's being used)
@ -215,6 +294,13 @@ namespace Microsoft.Toolkit.Uwp.Notifications
return guidS;
}
private static void CreateAndRegisterActivator()
{
var activatorType = CreateActivatorType(_aumid);
RegisterActivator(activatorType);
_registeredOnActivated = true;
}
private static void RegisterActivator(Type activatorType)
{
if (!DesktopBridgeHelpers.IsRunningAsUwp())
@ -248,7 +334,7 @@ namespace Microsoft.Toolkit.Uwp.Notifications
/// Gets whether the current process was activated due to a toast activation. If so, the OnActivated event will be triggered soon after process launch.
/// </summary>
/// <returns>True if the current process was activated due to a toast activation, otherwise false.</returns>
public static bool WasProcessToastActivated()
public static bool WasCurrentProcessToastActivated()
{
return Environment.GetCommandLineArgs().Contains(TOAST_ACTIVATED_LAUNCH_ARG);
}
@ -320,10 +406,10 @@ namespace Microsoft.Toolkit.Uwp.Notifications
/// <returns><see cref="ToastNotifier"/></returns>
public static ToastNotifier CreateToastNotifier()
{
if (_aumid != null)
if (_win32Aumid != null)
{
// Non-Desktop Bridge
return ToastNotificationManager.CreateToastNotifier(_aumid);
return ToastNotificationManager.CreateToastNotifier(_win32Aumid);
}
else
{
@ -335,7 +421,7 @@ namespace Microsoft.Toolkit.Uwp.Notifications
/// <summary>
/// Gets the <see cref="DesktopNotificationHistoryCompat"/> object.
/// </summary>
public static DesktopNotificationHistoryCompat History => new DesktopNotificationHistoryCompat(_aumid);
public static DesktopNotificationHistoryCompat History => new DesktopNotificationHistoryCompat(_win32Aumid);
/// <summary>
/// Gets a value indicating whether http images can be used within toasts. This is true if running with package identity (MSIX or sparse package).

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.5 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.9 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.6 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.1 KiB

Просмотреть файл

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '15.0'">
<VisualStudioVersion>15.0</VisualStudioVersion>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x86">
<Configuration>Debug</Configuration>
<Platform>x86</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x86">
<Configuration>Release</Configuration>
<Platform>x86</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|AnyCPU">
<Configuration>Debug</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|AnyCPU">
<Configuration>Release</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup>
<WapProjPath Condition="'$(WapProjPath)'==''">$(MSBuildExtensionsPath)\Microsoft\DesktopBridge\</WapProjPath>
</PropertyGroup>
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.props" />
<PropertyGroup>
<ProjectGuid>54349ab0-9e41-4aa6-849c-ec9ce80cdd2a</ProjectGuid>
<TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<DefaultLanguage>en-US</DefaultLanguage>
<AppxPackageSigningEnabled>false</AppxPackageSigningEnabled>
<EntryPointProjectUniqueName>..\Microsoft.Toolkit.Win32.WpfCore.SampleApp\Microsoft.Toolkit.Win32.WpfCore.SampleApp.csproj</EntryPointProjectUniqueName>
</PropertyGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<Content Include="Images\SplashScreen.scale-200.png" />
<Content Include="Images\LockScreenLogo.scale-200.png" />
<Content Include="Images\Square150x150Logo.scale-200.png" />
<Content Include="Images\Square44x44Logo.scale-200.png" />
<Content Include="Images\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Images\StoreLogo.png" />
<Content Include="Images\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Toolkit.Win32.WpfCore.SampleApp\Microsoft.Toolkit.Win32.WpfCore.SampleApp.csproj">
<SkipGetTargetFrameworkProperties>True</SkipGetTargetFrameworkProperties>
</ProjectReference>
</ItemGroup>
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
IgnorableNamespaces="uap rescap com desktop">
<Identity
Name="2f4b322e-d4a6-4e18-ba97-a8ee9232d8e5"
Publisher="CN=aleader"
Version="1.0.0.0" />
<Properties>
<DisplayName>Microsoft.Toolkit.Win32.WpfCore.SampleApp.PackagingProject</DisplayName>
<PublisherDisplayName>aleader</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14393.0" MaxVersionTested="10.0.14393.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="Microsoft.Toolkit.Win32.WpfCore.SampleApp.PackagingProject"
Description="Microsoft.Toolkit.Win32.WpfCore.SampleApp.PackagingProject"
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
<uap:DefaultTile Wide310x150Logo="Images\Wide310x150Logo.png" />
<uap:SplashScreen Image="Images\SplashScreen.png" />
</uap:VisualElements>
<Extensions>
<!--Register COM CLSID LocalServer32 registry key-->
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer Executable="Microsoft.Toolkit.Win32.WpfCore.SampleApp\Microsoft.Toolkit.Win32.WpfCore.SampleApp.exe" Arguments="-ToastActivated" DisplayName="Toast activator">
<com:Class Id="80cc4528-e348-11ea-87d0-0242ac130003" DisplayName="Toast activator"/>
</com:ExeServer>
</com:ComServer>
</com:Extension>
<!--Specify which CLSID to activate when toast clicked-->
<desktop:Extension Category="windows.toastNotificationActivation">
<desktop:ToastNotificationActivation ToastActivatorCLSID="80cc4528-e348-11ea-87d0-0242ac130003" />
</desktop:Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>

Просмотреть файл

@ -17,7 +17,7 @@ namespace Microsoft.Toolkit.Win32.WpfCore.SampleApp
// Listen to toast notification activations
DesktopNotificationManagerCompat.OnActivated += this.DesktopNotificationManagerCompat_OnActivated;
if (!DesktopNotificationManagerCompat.WasProcessToastActivated())
if (!DesktopNotificationManagerCompat.WasCurrentProcessToastActivated())
{
new MainWindow().Show();
}

Просмотреть файл

@ -125,17 +125,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{88C6FFBE-3
ThirdPartyNotices.txt = ThirdPartyNotices.txt
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Toolkit.Win32.WpfCore.SampleApp", "Microsoft.Toolkit.Win32.WpfCore.SampleApp\Microsoft.Toolkit.Win32.WpfCore.SampleApp.csproj", "{0037E4C9-7AF3-4ADD-8156-5AEFA6C36405}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Win32.WpfCore.SampleApp", "Microsoft.Toolkit.Win32.WpfCore.SampleApp\Microsoft.Toolkit.Win32.WpfCore.SampleApp.csproj", "{0037E4C9-7AF3-4ADD-8156-5AEFA6C36405}"
EndProject
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Microsoft.Toolkit.Win32.WpfCore.SampleApp.PackagingProject", "Microsoft.Toolkit.Win32.WpfCore.SampleApp.PackagingProject\Microsoft.Toolkit.Win32.WpfCore.SampleApp.PackagingProject.wapproj", "{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
UnitTests\UnitTests.Shared\UnitTests.Shared.projitems*{4e9466d1-d5aa-46ac-801b-c8fdab79f0d4}*SharedItemsImports = 13
UnitTests\UnitTests.HighPerformance.Shared\UnitTests.HighPerformance.Shared.projitems*{5524523e-db0f-41f7-a0d4-43128422a342}*SharedItemsImports = 4
UnitTests\UnitTests.Shared\UnitTests.Shared.projitems*{7878cd00-85e8-4d02-9757-8a43db4c6510}*SharedItemsImports = 5
UnitTests\UnitTests.Notifications.Shared\UnitTests.Notifications.Shared.projitems*{982cc826-aacd-4855-9075-430bb6ce40a9}*SharedItemsImports = 13
UnitTests\UnitTests.Shared\UnitTests.Shared.projitems*{a139968e-ad78-4e8c-93b8-9a5523bcac89}*SharedItemsImports = 4
UnitTests\UnitTests.HighPerformance.Shared\UnitTests.HighPerformance.Shared.projitems*{5524523e-db0f-41f7-a0d4-43128422a342}*SharedItemsImports = 4
UnitTests\UnitTests.Notifications.Shared\UnitTests.Notifications.Shared.projitems*{982cc826-aacd-4855-9075-430bb6ce40a9}*SharedItemsImports = 13
UnitTests\UnitTests.HighPerformance.Shared\UnitTests.HighPerformance.Shared.projitems*{9b3a94a6-0d29-4523-880b-6938e2efeef7}*SharedItemsImports = 13
UnitTests\UnitTests.Shared\UnitTests.Shared.projitems*{a139968e-ad78-4e8c-93b8-9a5523bcac89}*SharedItemsImports = 4
UnitTests\UnitTests.Notifications.Shared\UnitTests.Notifications.Shared.projitems*{bab1caf4-c400-4a7f-a987-c576de63cffd}*SharedItemsImports = 4
UnitTests\UnitTests.HighPerformance.Shared\UnitTests.HighPerformance.Shared.projitems*{d9bdbc68-3d0a-47fc-9c88-0bf769101644}*SharedItemsImports = 5
UnitTests\UnitTests.Notifications.Shared\UnitTests.Notifications.Shared.projitems*{efa96b3c-857e-4659-b942-6bef7719f4ca}*SharedItemsImports = 4
@ -1117,6 +1118,51 @@ Global
{0037E4C9-7AF3-4ADD-8156-5AEFA6C36405}.Release|x64.Build.0 = Release|Any CPU
{0037E4C9-7AF3-4ADD-8156-5AEFA6C36405}.Release|x86.ActiveCfg = Release|Any CPU
{0037E4C9-7AF3-4ADD-8156-5AEFA6C36405}.Release|x86.Build.0 = Release|Any CPU
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|ARM.ActiveCfg = Debug|ARM
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|ARM.Build.0 = Debug|ARM
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|ARM.Deploy.0 = Debug|ARM
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|ARM64.ActiveCfg = Debug|ARM64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|ARM64.Build.0 = Debug|ARM64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|ARM64.Deploy.0 = Debug|ARM64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|x64.ActiveCfg = Debug|x64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|x64.Build.0 = Debug|x64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|x64.Deploy.0 = Debug|x64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|x86.ActiveCfg = Debug|x86
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|x86.Build.0 = Debug|x86
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Debug|x86.Deploy.0 = Debug|x86
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|Any CPU.ActiveCfg = Debug|Any CPU
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|Any CPU.Build.0 = Debug|Any CPU
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|Any CPU.Deploy.0 = Debug|Any CPU
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|ARM.ActiveCfg = Release|ARM
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|ARM.Build.0 = Release|ARM
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|ARM.Deploy.0 = Release|ARM
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|ARM64.ActiveCfg = Release|ARM64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|ARM64.Build.0 = Release|ARM64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|ARM64.Deploy.0 = Release|ARM64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|x64.ActiveCfg = Release|x64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|x64.Build.0 = Release|x64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|x64.Deploy.0 = Release|x64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|x86.ActiveCfg = Release|x86
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|x86.Build.0 = Release|x86
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Native|x86.Deploy.0 = Release|x86
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|Any CPU.Build.0 = Release|Any CPU
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|Any CPU.Deploy.0 = Release|Any CPU
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|ARM.ActiveCfg = Release|ARM
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|ARM.Build.0 = Release|ARM
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|ARM.Deploy.0 = Release|ARM
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|ARM64.ActiveCfg = Release|ARM64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|ARM64.Build.0 = Release|ARM64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|ARM64.Deploy.0 = Release|ARM64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|x64.ActiveCfg = Release|x64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|x64.Build.0 = Release|x64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|x64.Deploy.0 = Release|x64
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|x86.ActiveCfg = Release|x86
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|x86.Build.0 = Release|x86
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1153,6 +1199,7 @@ Global
{804D0681-52F6-4E61-864A-699F0AB44B20} = {C79029AF-2E9B-4466-BAC4-1A41B281EAE6}
{88C6FFBE-322D-4CEA-842B-B2CB281D357D} = {CFA75BE0-5A44-45DE-8114-426A605B062B}
{0037E4C9-7AF3-4ADD-8156-5AEFA6C36405} = {9AD30620-667D-433C-9961-8D885EE7B762}
{54349AB0-9E41-4AA6-849C-EC9CE80CDD2A} = {9AD30620-667D-433C-9961-8D885EE7B762}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5403B0C4-F244-4F73-A35C-FE664D0F4345}