Windows 运行对话框 (Win+R) 用于从用户输入的字符串启动任意程序。它的酷之处在于它可以处理程序路径中的空格而无需任何转义。
举个例子,这个效果很好:
C:\Program Files\Git\git-bash --cd=./bin
。使用 CMD 或 Powershell,C:\Program
将被解释为程序路径,其余的将被解释为参数。
可以使用
CreateProcessW
或 ShellExecuteW
复制从路径中可能包含空格的字符串启动程序的行为吗? ShellExecuteW
需要一个单独的参数来表示程序路径及其参数,这似乎很难解决可能有空格的路径。 CreateProcessW
不传递 lpApplicationName
似乎可能是解决方案,但我无法让它工作(下面 Rust 中的示例代码 - 当然,任何语言的响应都可以)。
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(())
}
您链接的文档说:
参数可以是lpApplicationName
。在这种情况下,模块名称必须是NULL
字符串中的第一个空格分隔的标记lpCommandLine
因此
let command = r#"C:\Program Files\Git\git-bash --cd=./bin"#;
将被解释为带有参数 C:\Program
和 Files\Git\git-bash
的命令
--cd=./bin
运行对话框可能只是对您必须复制的输入进行自己的解析。