1

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?

AsPas
  • 359
  • 5
  • 22
  • There are 2 ways to start a new process on Windows. First by asking the kernel to start it directly. Second is asking shell to start it. I guess you need the second method due to it seems like it needs a shell to prepare something. – UltimaWeapon Jun 12 '20 at 11:05
  • Do I achieve this with `StartInfo.UseShellExecute = true`? If so, `true`is the default value. – AsPas Jun 12 '20 at 11:15
  • 1
    I'm not sure for .NET but in Win32 it uses `ShellExecute`. You may need to change `verb` to somethingelse than `open`. – UltimaWeapon Jun 12 '20 at 11:28
  • Thanks for the tip. I will look into that – AsPas Jun 12 '20 at 11:28
  • What happens if you try to launch from the command line `cmd /c "" path-to-config-file`? I don't have WSB, therefore I can't try it, sorry. What is file type for .wsb extension in the registry ''? What is the open command for this file type in `\HKEY_CLASSES_ROOT\\Shell\open\command`? – Pak Uula Jun 17 '20 at 05:07
  • @PakUula If I launch it from the CLI opens it as expected. The hive you mentioned `\HKEY_CLASSES_ROOT\.wsb\Shell\open\command` does not exist for me. It ends at `\HKEY_CLASSES_ROOT\.wsb` – AsPas Jun 17 '20 at 08:32
  • 1
    @AsPas, under HCR\.wsb there should be a key with file type, something like 'ms-sandbox'. The open command is defined for file type, not extension: e.g. HKEY_CLASSES_ROOT\ms-sandbox\Shell\open\command – Pak Uula Jun 17 '20 at 10:18
  • @PakUula I have found the key, this is what it's value looks like: `%SystemRoot%\System32\WindowsSandbox.exe "%1"` – AsPas Jun 17 '20 at 10:38

1 Answers1

3

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.

Community
  • 1
  • 1
Pak Uula
  • 2,750
  • 1
  • 8
  • 13
  • This is my current solution. But as you said I cannot wait for the sandbox process to finish, which is problematic. – AsPas Jun 17 '20 at 10:38
  • @AsPas, I added "Plan A" to invoke `WindowsSandbox.exe` directly – Pak Uula Jun 17 '20 at 11:02
  • I have tried it but I still get an exception. This time: `System.ComponentModel.Win32Exception: 'The system cannot find the file specified'`. This is witchcraft... – AsPas Jun 17 '20 at 11:04
  • @AsPas Variable expansion should hppen automatically when `UseShellExecute` is `true`. If it doesn't, replace `%SystemRoot%` with `C:\Windows` (or whatever path to Windows is in your system). – Pak Uula Jun 17 '20 at 11:07
  • I have tries this: `sbProc.StartInfo.FileName = @"C:\Windows\System32\WindowsSandbox.exe";` still same exception. – AsPas Jun 17 '20 at 11:09
  • @AsPas Wild idea - you run 32-bit .NET app on 64-bit Windows. When 32-bit process tries to invoke an executable or load a DLL from `C:\Windows\System32`, it is [automagically redirected](https://learn.microsoft.com/en-us/windows/win32/winprog64/file-system-redirector) to `C:\Windows\SysWOW64`. What is the value of `IntPtr.Size` in your app? – Pak Uula Jun 17 '20 at 11:25
  • `IntPtr.Size = 4` – AsPas Jun 17 '20 at 12:25
  • 1
    @AsPas, your application is 32 bit. You should either configure it to be 64 bit or use the following path: `%windir%\Sysnative\WindowsSandbox.exe`. For 32-bit applications the virtual directory `%windir%\Sysnative` points to 64-bit `System32` directory without redirection. – Pak Uula Jun 17 '20 at 12:33
  • 1
    This has solved my issue. It was indeed trying to find the 32-bit version of the sandbox in the WOW64 folder, which does not exist. Please update your answer to include this information and the link to the Microsoft page. Thank you very much for the help and patience!! – AsPas Jun 17 '20 at 12:37