Search code examples
c#windows-sandbox

Starting the Windows Sandbox from managed code


I'm trying to initialize the Windows Sandbox programatically. My objective is to generate a .wsb config file and then start it. Currently I am using Process.Start() method, but I keep getting an error on the Start() method.

This is the code:

var sbProc = new Process();
sbProc.StartInfo.FileName = configPath;
sbProc.Start();
sbProc.WaitForExit();

Throws: System.ComponentModel.Win32Exception: 'Application not found'.

I am sure the file exists as I have tried opening it by double-click and through the Command Line. Both worked like expected, so I'm assuming it is referring to the associated application (in this case Windows Sandbox).

I have tried adding:

sbProc.StartInfo.UseShellExecute = false;

Throws: System.ComponentModel.Win32Exception: 'The specified executable is not a valid application for this OS platform.'.

It's the same exception but a different message, which is actually very confusing. As said above, I am 100% sure my OS supports this feature; every requirement is supported and enabled. Is it possible that Process.Start() can't handle .wsb files and if so, how could I achieve what I am looking for?

I'm open for any suggestions and thanks in advance!

UPDATE:

I have tried changing the verb to Invoke and Start with the following code:

sbProc.StartInfo.Verb = "Start";

and

sbProc.StartInfo.Verb = "Invoke";

Throws:System.ComponentModel.Win32Exception: 'No application is associated with the specified file for this operation'

How can I associate and application with the file?


Solution

  • Windows Sandbox worked from double click in the Explorer and by cmd.exe /c start, but failed to launch programmatically in a C# app. The reason is that the C# app was 32 bit, while the OS was 64 bit.

    When the 32-bit app tried to invoke the Sandbox config, it (indirectly) tried to invoke %windir%\System32\WindowsSandbox.exe executable. BUT! When a 32-bit app tries to access %windir%\System32 on 64-bit Windows it is redirected to %windir%\SysWOW64 that contains 32-bit versions of system apps and DLLs. Since there is no 32-bit WindowsSandbox.exe, .NET framework was throwing exceptions System.ComponentModel.Win32Exception: 'Application not found'.

    There are two ways to launch 64-bit system apps from 32-bit user apps.

    Plan A

    Use %windir%\Sysnative path. It is available for 32-bit apps only and resolves to the true 64-bit System32 system folder.

    var sbProc = new Process();
    sbProc.StartInfo.FileName = "%SystemRoot%\Sysnative\WindowsSandbox.exe";
    sbProc.StartInfo.Arguments = "\"" +configPath + "\"";
    sbProc.StartInfo.UseShellExecute = true;
    sbProc.Start();
    sbProc.WaitForExit();
    

    I guess, in this case WaitForExit will wait until sandbox finishes. I'm not 100% sure, things can happen in Windows, but do expect.

    Plan B

    Plan A has the following risk: if in the future MS people rename the executable for the sandbox or add extra CLI switches, direct call might fail. You will have to modify your code.

    To avoid it you can use cmd.exe to launch the sandbox by start command. cmd.exe can invoke 64-bit system applications behind the curtains.

    var sbProc = new Process();
    sbProc.StartInfo.FileName = "cmd";
    sbProc.StartInfo.Arguments = "/c start \"\" \"" +configPath + "\"";
    sbProc.StartInfo.Start();
    sbProc.WaitForExit();
    

    The only issue is that WaitForExit will return as soon, as start finishes, not the sandbox . start doesn't wait for the launched process.