diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Assets/LockScreenLogo.scale-200.png b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/LockScreenLogo.scale-200.png
new file mode 100644
index 0000000000..67dacd6442
Binary files /dev/null and b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/LockScreenLogo.scale-200.png differ
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Assets/SplashScreen.scale-200.png b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/SplashScreen.scale-200.png
new file mode 100644
index 0000000000..81065653d3
Binary files /dev/null and b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/SplashScreen.scale-200.png differ
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Assets/Square150x150Logo.scale-200.png b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/Square150x150Logo.scale-200.png
new file mode 100644
index 0000000000..d735d9bac7
Binary files /dev/null and b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/Square150x150Logo.scale-200.png differ
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Assets/Square44x44Logo.scale-200.png b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/Square44x44Logo.scale-200.png
new file mode 100644
index 0000000000..4e6ec9fbc2
Binary files /dev/null and b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/Square44x44Logo.scale-200.png differ
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
new file mode 100644
index 0000000000..5f414a8a6d
Binary files /dev/null and b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png differ
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Assets/StoreLogo.png b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/StoreLogo.png
new file mode 100644
index 0000000000..b32ed0a8d7
Binary files /dev/null and b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/StoreLogo.png differ
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Assets/Wide310x150Logo.scale-200.png b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/Wide310x150Logo.scale-200.png
new file mode 100644
index 0000000000..e6d439a3e6
Binary files /dev/null and b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/Wide310x150Logo.scale-200.png differ
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Assets/youtube_logo_icon.png b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/youtube_logo_icon.png
new file mode 100644
index 0000000000..4452536d00
Binary files /dev/null and b/src/modules/cmdpal/Exts/YouTubeExtension/Assets/youtube_logo_icon.png differ
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Helper/LinkAction.cs b/src/modules/cmdpal/Exts/YouTubeExtension/Helper/LinkAction.cs
new file mode 100644
index 0000000000..38a9ee295e
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/Helper/LinkAction.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.CmdPal.Extensions.Helpers;
+
+namespace YouTubeExtension.Helper;
+
+internal sealed partial class LinkAction : InvokableCommand
+{
+ private readonly YouTubeVideo _video;
+
+ internal LinkAction(YouTubeVideo video)
+ {
+ this._video = video;
+ this.Name = "Open link";
+ this.Icon = new("\uE8A7");
+ }
+
+ public override CommandResult Invoke()
+ {
+ Process.Start(new ProcessStartInfo(_video.Link) { UseShellExecute = true });
+ return CommandResult.KeepOpen();
+ }
+}
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Helper/YouTubeHelper.cs b/src/modules/cmdpal/Exts/YouTubeExtension/Helper/YouTubeHelper.cs
new file mode 100644
index 0000000000..1f06df2f14
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/Helper/YouTubeHelper.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace YouTubeExtension.Helper;
+
+internal sealed class YouTubeHelper
+{
+ internal static string StateJsonPath()
+ {
+ // Get the path to our exe
+ var path = System.Reflection.Assembly.GetExecutingAssembly().Location;
+
+ // Get the directory of the exe
+ var directory = Path.GetDirectoryName(path) ?? string.Empty;
+
+ // now, the state is just next to the exe
+ return Path.Combine(directory, "state.json");
+ }
+}
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Helper/YouTubeVideo.cs b/src/modules/cmdpal/Exts/YouTubeExtension/Helper/YouTubeVideo.cs
new file mode 100644
index 0000000000..1ed45d0166
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/Helper/YouTubeVideo.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace YouTubeExtension.Helper;
+
+public sealed class YouTubeVideo
+{
+ public string Title { get; init; } = string.Empty;
+
+ public string Link { get; init; } = string.Empty;
+
+ public string Author { get; init; } = string.Empty;
+}
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Package.appxmanifest b/src/modules/cmdpal/Exts/YouTubeExtension/Package.appxmanifest
new file mode 100644
index 0000000000..9c9f402de0
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/Package.appxmanifest
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+ YouTube extension for cmdpal
+ A Lone Developer
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Pages/YouTubeAPIForm.cs b/src/modules/cmdpal/Exts/YouTubeExtension/Pages/YouTubeAPIForm.cs
new file mode 100644
index 0000000000..5dc092b2de
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/Pages/YouTubeAPIForm.cs
@@ -0,0 +1,76 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// 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;
+using System.Text;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
+using Microsoft.CmdPal.Extensions.Helpers;
+using YouTubeExtension.Helper;
+
+namespace YouTubeExtension.Pages;
+
+internal sealed partial class YouTubeAPIForm : Form
+{
+ public override string TemplateJson()
+ {
+ var json = $$"""
+ {
+ "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
+ "type": "AdaptiveCard",
+ "version": "1.5",
+ "body": [
+ {
+ "type": "Input.Text",
+ "style": "text",
+ "id": "apiKey",
+ "label": "API Key",
+ "isRequired": true,
+ "errorMessage": "API Key required"
+ }
+ ],
+ "actions": [
+ {
+ "type": "Action.Submit",
+ "title": "Save",
+ "data": {
+ "apiKey": "apiKey"
+ }
+ }
+ ]
+ }
+ """;
+ return json;
+ }
+
+ public override string DataJson() => throw new NotImplementedException();
+
+ public override string StateJson() => throw new NotImplementedException();
+
+ public override CommandResult SubmitForm(string payload)
+ {
+ var formInput = JsonNode.Parse(payload);
+ if (formInput == null)
+ {
+ return CommandResult.GoHome();
+ }
+
+ // get the name and url out of the values
+ var formApiKey = formInput["apiKey"] ?? string.Empty;
+
+ // Construct a new json blob with the name and url
+ var json = $$"""
+ {
+ "apiKey": "{{formApiKey}}"
+ }
+ """;
+
+ File.WriteAllText(YouTubeHelper.StateJsonPath(), json);
+ return CommandResult.GoHome();
+ }
+}
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Pages/YouTubeAPIPage.cs b/src/modules/cmdpal/Exts/YouTubeExtension/Pages/YouTubeAPIPage.cs
new file mode 100644
index 0000000000..1a4f4a557b
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/Pages/YouTubeAPIPage.cs
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.CmdPal.Extensions;
+using Microsoft.CmdPal.Extensions.Helpers;
+
+namespace YouTubeExtension.Pages;
+
+internal sealed partial class YouTubeAPIPage : FormPage
+{
+ private readonly YouTubeAPIForm apiForm = new();
+
+ public override IForm[] Forms() => [apiForm];
+
+ public YouTubeAPIPage()
+ {
+ Name = "YouTube API";
+ Icon = new("https://www.youtube.com/favicon.ico");
+ }
+}
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Pages/YouTubeVideosPage.cs b/src/modules/cmdpal/Exts/YouTubeExtension/Pages/YouTubeVideosPage.cs
new file mode 100644
index 0000000000..97971774a7
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/Pages/YouTubeVideosPage.cs
@@ -0,0 +1,93 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Text.Json.Nodes;
+using System.Threading.Tasks;
+using Microsoft.CmdPal.Extensions;
+using Microsoft.CmdPal.Extensions.Helpers;
+using YouTubeExtension.Helper;
+
+namespace YouTubeExtension;
+
+internal sealed partial class YouTubeVideosPage : DynamicListPage
+{
+ public YouTubeVideosPage()
+ {
+ Icon = new("https://www.youtube.com/favicon.ico");
+ Name = "YouTube";
+ }
+
+ public override ISection[] GetItems(string query)
+ {
+ return DoGetItems(query).GetAwaiter().GetResult(); // Fetch and await the task synchronously
+ }
+
+ private async Task DoGetItems(string query)
+ {
+ // Fetch YouTube videos based on the query
+ List items = await GetYouTubeVideos(query);
+
+ // Create a section and populate it with the video results
+ var section = new ListSection()
+ {
+ Title = "Search Results",
+ Items = items.Select(video => new ListItem(new LinkAction(video))
+ {
+ Title = video.Title,
+ Subtitle = $"{video.Author}",
+ }).ToArray(),
+ };
+
+ return new[] { section }; // Properly return an array of sections
+ }
+
+ // Method to fetch videos from YouTube API
+ private static async Task> GetYouTubeVideos(string query)
+ {
+ var state = File.ReadAllText(YouTubeHelper.StateJsonPath());
+ var jsonState = JsonNode.Parse(state);
+ var apiKey = jsonState["apiKey"]?.ToString() ?? string.Empty;
+
+ var videos = new List();
+
+ using HttpClient client = new HttpClient();
+ {
+ try
+ {
+ var response = await client.GetStringAsync($"https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&q={query}&key={apiKey}");
+ var json = JsonNode.Parse(response);
+
+ if (json?["items"] is JsonArray itemsArray)
+ {
+ foreach (var item in itemsArray)
+ {
+ videos.Add(new YouTubeVideo
+ {
+ Title = item["snippet"]?["title"]?.ToString() ?? string.Empty,
+ Link = $"https://www.youtube.com/watch?v={item["id"]?["videoId"]?.ToString()}",
+ Author = item["snippet"]?["channelTitle"]?.ToString() ?? string.Empty,
+ });
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ // Handle any errors from the API call or parsing
+ videos.Add(new YouTubeVideo
+ {
+ Title = "Error fetching data",
+ Link = string.Empty,
+ Author = $"Error: {ex.Message}",
+ });
+ }
+ }
+
+ return videos;
+ }
+}
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Program.cs b/src/modules/cmdpal/Exts/YouTubeExtension/Program.cs
new file mode 100644
index 0000000000..3bc4589d61
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/Program.cs
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Threading;
+using Microsoft.CmdPal.Extensions;
+
+namespace YouTubeExtension;
+
+public class Program
+{
+ [MTAThread]
+ public static void Main(string[] args)
+ {
+ if (args.Length > 0 && args[0] == "-RegisterProcessAsComServer")
+ {
+ using ExtensionServer server = new();
+ var extensionDisposedEvent = new ManualResetEvent(false);
+ var extensionInstance = new SampleExtension(extensionDisposedEvent);
+
+ // We are instantiating an extension instance once above, and returning it every time the callback in RegisterExtension below is called.
+ // This makes sure that only one instance of SampleExtension is alive, which is returned every time the host asks for the IExtension object.
+ // If you want to instantiate a new instance each time the host asks, create the new instance inside the delegate.
+ server.RegisterExtension(() => extensionInstance);
+
+ // This will make the main thread wait until the event is signalled by the extension class.
+ // Since we have single instance of the extension object, we exit as sooon as it is disposed.
+ extensionDisposedEvent.WaitOne();
+ }
+ else
+ {
+ Console.WriteLine("Not being launched as a Extension... exiting.");
+ }
+ }
+}
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/Properties/launchSettings.json b/src/modules/cmdpal/Exts/YouTubeExtension/Properties/launchSettings.json
new file mode 100644
index 0000000000..5a6a96b58e
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/Properties/launchSettings.json
@@ -0,0 +1,11 @@
+{
+ "profiles": {
+ "YouTubeExtension (Package)": {
+ "commandName": "MsixPackage",
+ "commandLineArgs": "-RegisterProcessAsComServer"
+ },
+ "YouTubeExtension (Unpackaged)": {
+ "commandName": "Project"
+ }
+ }
+}
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/SampleExtension.cs b/src/modules/cmdpal/Exts/YouTubeExtension/SampleExtension.cs
new file mode 100644
index 0000000000..e4e21e341d
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/SampleExtension.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using Microsoft.CmdPal.Extensions;
+
+namespace YouTubeExtension;
+
+[ComVisible(true)]
+[Guid("95696eff-5c44-41ad-8f64-c2182ec9e3fd")]
+[ComDefaultInterface(typeof(IExtension))]
+public sealed partial class SampleExtension : IExtension
+{
+ private readonly ManualResetEvent _extensionDisposedEvent;
+
+ public SampleExtension(ManualResetEvent extensionDisposedEvent)
+ {
+ this._extensionDisposedEvent = extensionDisposedEvent;
+ }
+
+ public object GetProvider(ProviderType providerType)
+ {
+ switch (providerType)
+ {
+ case ProviderType.Commands:
+ return new YouTubeExtensionActionsProvider();
+ default:
+ return null;
+ }
+ }
+
+ public void Dispose()
+ {
+ this._extensionDisposedEvent.Set();
+ }
+}
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/YouTubeExtension.csproj b/src/modules/cmdpal/Exts/YouTubeExtension/YouTubeExtension.csproj
new file mode 100644
index 0000000000..cd8089d212
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/YouTubeExtension.csproj
@@ -0,0 +1,53 @@
+
+
+
+ WinExe
+ YouTubeExtension
+ app.manifest
+ win-$(Platform).pubxml
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/YouTubeExtensionCommandsProvider.cs b/src/modules/cmdpal/Exts/YouTubeExtension/YouTubeExtensionCommandsProvider.cs
new file mode 100644
index 0000000000..a88c3c7ee2
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/YouTubeExtensionCommandsProvider.cs
@@ -0,0 +1,92 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.CmdPal.Extensions;
+using Microsoft.CmdPal.Extensions.Helpers;
+using Windows.UI.ApplicationSettings;
+using YouTubeExtension.Helper;
+using YouTubeExtension.Pages;
+
+namespace YouTubeExtension;
+
+public partial class YouTubeExtensionActionsProvider : ICommandProvider
+{
+ public string DisplayName => $"YouTube";
+
+ public IconDataType Icon => new(string.Empty);
+
+ private readonly IListItem[] _commands = [
+ new ListItem(new YouTubeVideosPage()) { Title = "Search Videos", Subtitle = "YouTube" },
+ ];
+
+ private readonly YouTubeAPIPage apiPage = new();
+
+#pragma warning disable CA1816 // Dispose methods should call SuppressFinalize
+ public void Dispose() => throw new NotImplementedException();
+#pragma warning restore CA1816 // Dispose methods should call SuppressFinalize
+
+ public IListItem[] TopLevelCommands()
+ {
+ return TopLevelCommandsAsync().GetAwaiter().GetResult();
+ }
+
+ public async Task TopLevelCommandsAsync()
+ {
+ var settingsPath = YouTubeHelper.StateJsonPath();
+
+ // Check if the settings file exists
+ if (!File.Exists(settingsPath))
+ {
+ return new[] { new ListItem(apiPage) { Title = "YouTube", Subtitle = "Enter your API key." } };
+ }
+
+ // Read the file and parse the API key
+ var state = File.ReadAllText(settingsPath);
+ var jsonState = System.Text.Json.Nodes.JsonNode.Parse(state);
+ var apiKey = jsonState?["apiKey"]?.ToString() ?? string.Empty;
+
+ // Validate the API key using YouTube API
+ if (string.IsNullOrWhiteSpace(apiKey) || !await IsApiKeyValid(apiKey))
+ {
+ return new[] { new ListItem(apiPage) { Title = "YouTube", Subtitle = "Current API Invalid. Please enter a new API key." } };
+ }
+
+ // If file exists and API key is valid, return commands
+ return _commands;
+ }
+
+ // Method to check if the API key is valid by making a simple request to the YouTube API
+ private static async Task IsApiKeyValid(string apiKey)
+ {
+ using HttpClient client = new HttpClient();
+ {
+ try
+ {
+ // Make a simple request to verify the API key, such as fetching a video
+ var response = await client.GetAsync($"https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&q=test&key={apiKey}");
+
+ // If the response status code is 200, the API key is valid
+ if (response.IsSuccessStatusCode)
+ {
+ return true;
+ }
+
+ // Optionally, handle other status codes and log errors
+ return false;
+ }
+ catch
+ {
+ // If any exception occurs (e.g., network error), consider the API key invalid
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/modules/cmdpal/Exts/YouTubeExtension/app.manifest b/src/modules/cmdpal/Exts/YouTubeExtension/app.manifest
new file mode 100644
index 0000000000..bcafb9bc5b
--- /dev/null
+++ b/src/modules/cmdpal/Exts/YouTubeExtension/app.manifest
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PerMonitorV2
+
+
+
diff --git a/src/modules/cmdpal/WindowsCommandPalette.sln b/src/modules/cmdpal/WindowsCommandPalette.sln
index 0b74e7135d..5a3dfc00af 100644
--- a/src/modules/cmdpal/WindowsCommandPalette.sln
+++ b/src/modules/cmdpal/WindowsCommandPalette.sln
@@ -42,6 +42,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SSHKeychainExtension", "ext
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SamplePagesExtension", "exts\SamplePagesExtension\SamplePagesExtension.csproj", "{399B53F1-5AA6-4FE0-8C3C-66E07B84E6F1}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YouTubeExtension", "Exts\YouTubeExtension\YouTubeExtension.csproj", "{276243F6-4B25-411C-B110-1E7DB575F13D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
@@ -198,6 +200,18 @@ Global
{399B53F1-5AA6-4FE0-8C3C-66E07B84E6F1}.Release|x64.ActiveCfg = Release|x64
{399B53F1-5AA6-4FE0-8C3C-66E07B84E6F1}.Release|x64.Build.0 = Release|x64
{399B53F1-5AA6-4FE0-8C3C-66E07B84E6F1}.Release|x64.Deploy.0 = Release|x64
+ {276243F6-4B25-411C-B110-1E7DB575F13D}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {276243F6-4B25-411C-B110-1E7DB575F13D}.Debug|ARM64.Build.0 = Debug|ARM64
+ {276243F6-4B25-411C-B110-1E7DB575F13D}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {276243F6-4B25-411C-B110-1E7DB575F13D}.Debug|x64.ActiveCfg = Debug|x64
+ {276243F6-4B25-411C-B110-1E7DB575F13D}.Debug|x64.Build.0 = Debug|x64
+ {276243F6-4B25-411C-B110-1E7DB575F13D}.Debug|x64.Deploy.0 = Debug|x64
+ {276243F6-4B25-411C-B110-1E7DB575F13D}.Release|ARM64.ActiveCfg = Release|ARM64
+ {276243F6-4B25-411C-B110-1E7DB575F13D}.Release|ARM64.Build.0 = Release|ARM64
+ {276243F6-4B25-411C-B110-1E7DB575F13D}.Release|ARM64.Deploy.0 = Release|ARM64
+ {276243F6-4B25-411C-B110-1E7DB575F13D}.Release|x64.ActiveCfg = Release|x64
+ {276243F6-4B25-411C-B110-1E7DB575F13D}.Release|x64.Build.0 = Release|x64
+ {276243F6-4B25-411C-B110-1E7DB575F13D}.Release|x64.Deploy.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -219,6 +233,7 @@ Global
{7F6796A4-4233-4CEC-914F-95EC7A5283A0} = {272D0E9A-8FC3-49F5-8FAD-79ABAE8AB1E4}
{77D99BE0-F69C-4F27-8153-951CEC5110FE} = {B7FF739F-7716-4FC3-B622-705486187B87}
{399B53F1-5AA6-4FE0-8C3C-66E07B84E6F1} = {B7FF739F-7716-4FC3-B622-705486187B87}
+ {276243F6-4B25-411C-B110-1E7DB575F13D} = {B7FF739F-7716-4FC3-B622-705486187B87}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BC94BFC2-A741-4978-B6A4-9E01B7660E6B}