forked from microsoft/devhome
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Inbox Windows Sandbox Environments extension (microsoft#2752)
* Windows Sandbox Extension * Launch Windows Sandbox * Tracelogging and Appx Check * Fix packaging for WSB extension * Fix appx package check * Remove any cpu * Only return Compute System provider if OC is enabled and appx is not installed * Add publish profiles * Change compute system display name * Start and stop Windows Sandbox * Address PR comments * Fix race * Empty Compute System ID * Set CPU Count * Set compute system ID. * Address PR comments * Locking Windows Sandbox in resources file * Fix indentation in appx package * Remove not implemented exceptions * Set constants for default memory and storage * Rename app description resource * Fix packaging * Fix hang on stopping already stopped Compute System --------- Co-authored-by: kevinve <[email protected]>
- Loading branch information
Showing
24 changed files
with
1,374 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.53 MB
extensions/WindowsSandboxExtension/Assets/windows-sandbox-thumbnail.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace WindowsSandboxExtension; | ||
|
||
internal sealed class Constants | ||
{ | ||
public const string WindowsSandboxExe = "WindowsSandbox.exe"; | ||
public const string ProviderDisplayName = "Windows Sandbox"; | ||
public const string ProviderId = "Microsoft.WindowsSandbox"; | ||
public const string Thumbnail = "ms-appx:///Assets/windows-sandbox-thumbnail.jpg"; | ||
|
||
// We use different icon locations for different builds. Note these are ms-resource URIs, but are used by Dev Home to load the providers icon. | ||
// from the extension package. Extensions that implement the IComputeSystemProvider interface must provide a provider icon in this format. | ||
// Dev Home will use SHLoadIndirectString (https://learn.microsoft.com/windows/win32/api/shlwapi/nf-shlwapi-shloadindirectstring) to load the | ||
// location of the icon from the extension package.Once it gets this location, it will load the icon from the path and display it in the UI. | ||
// Icons should be located in an extension resource.pri file which is generated at build time. | ||
// See the MakePri.exe documentation for how you can view what is in the resource.pri file, so you can find the location of your icon. | ||
// https://learn.microsoft.com/windows/uwp/app-resources/makepri-exe-command-options. (use MakePri.exe in a VS Developer Command Prompt or | ||
// Powershell window) | ||
#if CANARY_BUILD | ||
public const string ExtensionIcon = "ms-resource://Microsoft.Windows.DevHome.Canary/Files/Assets/windows-sandbox-icon.png"; | ||
#elif STABLE_BUILD | ||
public const string ExtensionIcon = "ms-resource://Microsoft.Windows.DevHome/Files/Assets/windows-sandbox-icon.png"; | ||
#else | ||
public const string ExtensionIcon = "ms-resource://Microsoft.Windows.DevHome.Dev/Files/Assets/windows-sandbox-icon.png"; | ||
#endif | ||
} |
51 changes: 51 additions & 0 deletions
51
extensions/WindowsSandboxExtension/Helpers/DependencyChecker.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.Linq; | ||
using System.Management; | ||
using System.Security.Principal; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Windows.Management.Deployment; | ||
using WinRT; | ||
|
||
namespace WindowsSandboxExtension.Helpers; | ||
|
||
internal sealed class DependencyChecker | ||
{ | ||
private const string OptionalComponentName = "Containers-DisposableClientVM"; | ||
private const string PackageFamilyName = "MicrosoftWindows.WindowsSandbox_cw5n1h2txyewy"; | ||
|
||
public static bool IsOptionalComponentEnabled() | ||
{ | ||
var searcher = new ManagementObjectSearcher($"SELECT InstallState FROM Win32_OptionalFeature WHERE Name = '{OptionalComponentName}'"); | ||
var collection = searcher.Get(); | ||
|
||
foreach (ManagementObject instance in collection) | ||
{ | ||
if (instance["InstallState"] != null) | ||
{ | ||
var state = Convert.ToInt32(instance.GetPropertyValue("InstallState"), CultureInfo.InvariantCulture); | ||
|
||
// 1 means the feature is enabled | ||
return state == 1; | ||
} | ||
} | ||
|
||
// Return false if the feature is not found | ||
return false; | ||
} | ||
|
||
public static bool IsNewWindowsSandboxExtensionInstalled() | ||
{ | ||
PackageManager packageManager = new PackageManager(); | ||
|
||
var securityId = WindowsIdentity.GetCurrent().Owner?.ToString(); | ||
var packages = packageManager.FindPackagesForUser(securityId, PackageFamilyName); | ||
|
||
return packages.Any(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Windows.Storage; | ||
|
||
namespace WindowsSandboxExtension.Helpers; | ||
|
||
public class Logging | ||
{ | ||
public static readonly string LogExtension = ".dhlog"; | ||
|
||
public static readonly string LogFolderName = "Logs"; | ||
|
||
public static readonly string DefaultLogFileName = "WindowsSandbox"; | ||
|
||
private static readonly Lazy<string> _logFolderRoot = new(() => Path.Combine(ApplicationData.Current.TemporaryFolder.Path, LogFolderName)); | ||
|
||
public static readonly string LogFolderRoot = _logFolderRoot.Value; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Microsoft.Windows.ApplicationModel.Resources; | ||
using Serilog; | ||
|
||
namespace WindowsSandboxExtension.Helpers; | ||
|
||
internal sealed class Resources | ||
{ | ||
private static ResourceLoader? _resourceLoader; | ||
|
||
public static string GetResource(string identifier, ILogger? log = null) | ||
{ | ||
try | ||
{ | ||
if (_resourceLoader == null) | ||
{ | ||
var path = ResourceLoader.GetDefaultResourceFilePath(); | ||
_resourceLoader = new ResourceLoader(path); | ||
} | ||
|
||
return _resourceLoader.GetString(identifier); | ||
} | ||
catch (Exception ex) | ||
{ | ||
log?.Error(ex, $"Failed loading resource: {identifier}"); | ||
|
||
// If we fail, load the original identifier so it is obvious which resource is missing. | ||
return identifier; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
SetForegroundWindow |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System.Diagnostics; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Windows.AppLifecycle; | ||
using Microsoft.Windows.DevHome.SDK; | ||
using Serilog; | ||
using Windows.ApplicationModel.Activation; | ||
using WindowsSandboxExtension.Helpers; | ||
using WindowsSandboxExtension.Providers; | ||
using WinRT; | ||
|
||
namespace WindowsSandboxExtension; | ||
|
||
public sealed class Program | ||
{ | ||
public static IHost? Host | ||
{ | ||
get; set; | ||
} | ||
|
||
[MTAThread] | ||
public static void Main([System.Runtime.InteropServices.WindowsRuntime.ReadOnlyArray] string[] args) | ||
{ | ||
// Set up Logging | ||
Environment.SetEnvironmentVariable("DEVHOME_LOGS_ROOT", Path.Join(Helpers.Logging.LogFolderRoot, "WindowsSandbox")); | ||
var configuration = new ConfigurationBuilder() | ||
.AddJsonFile("appsettings_WindowsSandbox.json") | ||
.Build(); | ||
Log.Logger = new LoggerConfiguration() | ||
.ReadFrom.Configuration(configuration) | ||
.CreateLogger(); | ||
|
||
Log.Information($"Launched with args: {string.Join(' ', args.ToArray())}"); | ||
|
||
// Force the app to be single instanced. | ||
// Get or register the main instance. | ||
var mainInstance = AppInstance.FindOrRegisterForKey("mainInstance"); | ||
var activationArgs = AppInstance.GetCurrent().GetActivatedEventArgs(); | ||
if (!mainInstance.IsCurrent) | ||
{ | ||
Log.Information($"Not main instance, redirecting."); | ||
mainInstance.RedirectActivationToAsync(activationArgs).AsTask().Wait(); | ||
Log.CloseAndFlush(); | ||
return; | ||
} | ||
|
||
// Build the host container before handling activation. | ||
BuildHostContainer(); | ||
|
||
// Register for activation redirection. | ||
AppInstance.GetCurrent().Activated += AppActivationRedirected; | ||
|
||
if (args.Length > 0 && args[0] == "-RegisterProcessAsComServer") | ||
{ | ||
HandleCOMServerActivation(); | ||
} | ||
else | ||
{ | ||
Log.Warning("Not being launched as a ComServer... exiting."); | ||
} | ||
|
||
Log.CloseAndFlush(); | ||
} | ||
|
||
private static void AppActivationRedirected(object? sender, Microsoft.Windows.AppLifecycle.AppActivationArguments activationArgs) | ||
{ | ||
Log.Information($"Redirected with kind: {activationArgs.Kind}"); | ||
|
||
// Handle COM server. | ||
if (activationArgs.Kind == ExtendedActivationKind.Launch) | ||
{ | ||
var launchActivatedEventArgs = activationArgs.Data as ILaunchActivatedEventArgs; | ||
var args = launchActivatedEventArgs?.Arguments.Split(); | ||
|
||
if (args?.Length > 0 && args[1] == "-RegisterProcessAsComServer") | ||
{ | ||
Log.Information($"Activation COM Registration Redirect: {string.Join(' ', args.ToList())}"); | ||
HandleCOMServerActivation(); | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Creates the host container for the Windows Sandbox Extension application. This can be used to register | ||
/// services and other dependencies throughout the application. | ||
/// </summary> | ||
private static void BuildHostContainer() | ||
{ | ||
Host = Microsoft.Extensions.Hosting.Host. | ||
CreateDefaultBuilder(). | ||
UseContentRoot(AppContext.BaseDirectory). | ||
UseDefaultServiceProvider((context, options) => | ||
{ | ||
options.ValidateOnBuild = true; | ||
}). | ||
ConfigureServices((context, services) => | ||
{ | ||
// Services | ||
services.AddHttpClient(); | ||
services.AddSingleton<IComputeSystemProvider, WindowsSandboxProvider>(); | ||
services.AddSingleton<WindowsSandboxExtension>(); | ||
}). | ||
Build(); | ||
} | ||
|
||
private static void HandleCOMServerActivation() | ||
{ | ||
Debug.Assert(Host != null, "Host is null"); | ||
Log.Information($"Activating COM Server"); | ||
|
||
// Register and run COM server. | ||
// This could be called by either of the COM registrations, we will do them all to avoid deadlock and bind all on the extension's lifetime. | ||
using var extensionServer = new Microsoft.Windows.DevHome.SDK.ExtensionServer(); | ||
var windowsSandboxExtension = Host.Services.GetRequiredService(typeof(WindowsSandboxExtension)).As<WindowsSandboxExtension>(); | ||
|
||
// We are instantiating extension instance once above, and returning it every time the callback in RegisterExtension below is called. | ||
// This makes sure that only one instance of the extension 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. | ||
extensionServer.RegisterExtension(() => windowsSandboxExtension, true); | ||
|
||
// 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 soon as it is disposed. | ||
windowsSandboxExtension.ExtensionDisposedEvent.WaitOne(); | ||
Log.Information($"Extension is disposed."); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
extensions/WindowsSandboxExtension/Properties/PublishProfiles/win-arm64.pubxml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!-- | ||
https://go.microsoft.com/fwlink/?LinkID=208121. | ||
--> | ||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<PropertyGroup> | ||
<PublishProtocol>FileSystem</PublishProtocol> | ||
<Platform>arm64</Platform> | ||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier> | ||
<SelfContained>true</SelfContained> | ||
<PublishSingleFile>False</PublishSingleFile> | ||
<PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun> | ||
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun> | ||
<PublishReadyToRunComposite Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRunComposite> | ||
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed> | ||
</PropertyGroup> | ||
</Project> |
17 changes: 17 additions & 0 deletions
17
extensions/WindowsSandboxExtension/Properties/PublishProfiles/win-x64.pubxml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!-- | ||
https://go.microsoft.com/fwlink/?LinkID=208121. | ||
--> | ||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<PropertyGroup> | ||
<PublishProtocol>FileSystem</PublishProtocol> | ||
<Platform>x64</Platform> | ||
<RuntimeIdentifier>win-x64</RuntimeIdentifier> | ||
<SelfContained>true</SelfContained> | ||
<PublishSingleFile>False</PublishSingleFile> | ||
<PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun> | ||
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun> | ||
<PublishReadyToRunComposite Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRunComposite> | ||
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed> | ||
</PropertyGroup> | ||
</Project> |
17 changes: 17 additions & 0 deletions
17
extensions/WindowsSandboxExtension/Properties/PublishProfiles/win-x86.pubxml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!-- | ||
https://go.microsoft.com/fwlink/?LinkID=208121. | ||
--> | ||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<PropertyGroup> | ||
<PublishProtocol>FileSystem</PublishProtocol> | ||
<Platform>x86</Platform> | ||
<RuntimeIdentifier>win-x86</RuntimeIdentifier> | ||
<SelfContained>true</SelfContained> | ||
<PublishSingleFile>False</PublishSingleFile> | ||
<PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun> | ||
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun> | ||
<PublishReadyToRunComposite Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRunComposite> | ||
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed> | ||
</PropertyGroup> | ||
</Project> |
8 changes: 8 additions & 0 deletions
8
extensions/WindowsSandboxExtension/Properties/launchSettings.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"profiles": { | ||
"WindowsSandboxExtension": { | ||
"commandName": "Project", | ||
"commandLineArgs": "-RegisterProcessAsComServer" | ||
} | ||
} | ||
} |
Oops, something went wrong.