使用“CreateProcessW”或“ShellExecuteExW”复制 Windows 运行行为?

问题描述 投票:0回答:1

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(())
}
windows winapi rust windows-rs
1个回答
0
投票

您链接的文档说:

lpApplicationName
参数可以是
NULL
。在这种情况下,模块名称必须是
lpCommandLine
字符串中的第一个空格分隔的标记

因此

let command = r#"C:\Program Files\Git\git-bash --cd=./bin"#;
将被解释为带有参数
C:\Program
Files\Git\git-bash
 的命令 
--cd=./bin

运行对话框可能只是对您必须复制的输入进行自己的解析。

© www.soinside.com 2019 - 2024. All rights reserved.