powershell - PowerShell和WinApi

标签 powershell winapi

我正在尝试这个:

$signature = @'
[DllImport("shell32.dll")]
public static extern int ShellExecuteW(
  int    hwnd,
  string lpOperation,
  string lpFile,
  string lpParameters,
  string lpDirectory,
  int     nShowCmd
);
'@

$exec = Add-Type -memberDefinition $signature -name "win" -namespace Win32Functions -passThru

$exec::ShellExecuteW(0, "open", "notepad.exe", 0, 0, 1)

但是记事本无法启动。如何正确写下来?

最佳答案

立即修复是双重的:

  • [DllImport("shell32.dll")]->[DllImport("Shell32.dll", CharSet = CharSet.Unicode)]
  • 因为您显式地指定了ShellExecuteW(API函数的Unicode版本),所以您必须通过属性中的CharSet字段声明该事实。[1]
  • 虽然不是严格必需的,但int hwnd应该是IntPtr hwnd
  • $exec::ShellExecuteW(0, "open", "notepad.exe", 0, 0, 1)->$exec::ShellExecute(0, "open", "notepad.exe", [NullString]::Value, [NullString]::Value, 1)
  • 注意使用[NullString]::Valuenull传递给string类型的参数;默认情况下,PowerShell将字符串上下文中的$null视为空字符串,而不是null;但是,在这种特殊情况下,空字符串(以及$null)也可以工作。

  • 放在一起:
    $exec = Add-Type -name "win" -namespace Win32Functions -passThru -memberDefinition @'
    [DllImport("shell32.dll", CharSet=CharSet.Unicode)]
    public static extern int ShellExecuteW(
      IntPtr hwnd,
      string lpOperation,
      string lpFile,
      string lpParameters,
      string lpDirectory,
      int    nShowCmd
    );
    '@
    
    $exec::ShellExecuteW(
      0, 
      'open', 
      'notepad.exe', 
      [NullString]::Value, 
      [NullString]::Value, 
      1
    )
    

    退后一步: Start-Process cmdlet允许您执行相同操作,而无需按需编译的P / Invoke声明:
    # Use -WorkingDirectory, if  needed.
    Start-Process Notepad.Exe -Verb Open -WindowStyle Normal
    

    [1]实际上,省略W后缀(ShellExecute)而不指定CharSet值也是可行的,尽管the docs表示随后会调用ANSI版本。但是,在实践中我看不到这一点:即使将带有ANSI范围之外的字符(例如'file€§ü.txt')的参数显式传递给函数的ANSI版本,它们似乎也可以正确传递给记事本。相反,即使明确地以Unicode版本为目标,将这样的字符串传递给控制台应用程序似乎也无法正确传递它们。

    关于powershell - PowerShell和WinApi,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61170518/

    相关文章:

    sql - 如何在 Powershell 中使用 SQLCMD 将结果导出到 Excel

    regex - PowerShell正则表达式匹配IP不会继续且IP不会跟随

    azure - 如何从 azure Devops 管道运行 powershell 命令到本地远程服务器

    azure - 将 Exchange Online powershell v3 连接到 Multi-Tenancy 应用程序中的委派访问

    c++ - 如何初始化一个点数组?

    c++ - 子类编辑控件接受点,尽管它不应该接受

    c++ - 如何在 Win32 上加速具有大纹理的屏幕外 OpenGL 渲染?

    c - PlaySound 功能奇怪的行为

    powershell - 使用 init.ps1 和 nuget 将文件复制到解决方案文件夹

    c++ - 单词下的波浪线 (Win32)