The Windows Run dialog (Win+R) is used to launch arbitrary programs from a user-inputted string. What's cool about it is that it can handle spaces in the program path without any escaping.
So for example, this works fine: C:\Program Files\Git\git-bash --cd=./bin
. With CMD or Powershell, C:\Program
would be interpreted as the program path, and the rest as arguments.
Can this behavior of launching a program from a string that might have spaces in its path be replicated using CreateProcessW
or ShellExecuteW
? ShellExecuteW
needs a separate parameter for the program path and its arguments, which seems tough to work-around with paths that may have spaces. CreateProcessW
without passing an lpApplicationName
seemed like it could be the solution, but I can't get it working (sample code in Rust below - responses with any lang are fine of course).
use windows::core::PWSTR;
use windows::Win32::Foundation::CloseHandle;
use windows::Win32::System::Threading::{
CreateProcessW, PROCESS_CREATION_FLAGS, PROCESS_INFORMATION,
STARTUPINFOW,
};
pub fn shell_exec() -> anyhow::Result<()> {
// Arbitrary command to execute. The command in the variable doesn't work
// but this path does: r#"C:\Program Files\Git\git-bash"#;
let command = r#"C:\Program Files\Git\git-bash --cd=./bin"#;
let command_utf16: Vec<u16> =
command.encode_utf16().chain(Some(0)).collect();
let mut si = STARTUPINFOW::default();
let mut pi = PROCESS_INFORMATION::default();
unsafe {
CreateProcessW(
None,
PWSTR(command_utf16.as_ptr() as *mut u16),
None,
None,
false,
PROCESS_CREATION_FLAGS::default(),
None,
None,
&mut si,
&mut pi,
)?;
println!("Command executed successfully.");
CloseHandle(pi.hProcess)?;
CloseHandle(pi.hThread)?;
}
Ok(())
}
possible use SHEvaluateSystemCommandTemplate
SHSTDAPI SHEvaluateSystemCommandTemplate(
_In_ PCWSTR pszCmdTemplate,
_Out_ PWSTR *ppszApplication,
_Out_opt_ PWSTR *ppszCommandLine,
_Out_opt_ PWSTR *ppszParameters
);
which exactly design for this purpose