如何从Powershell调用GetStdHandle、GetConsoleMode?

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

尝试使用

Add-Type
方法从 Powershell 脚本读取当前 Windows 控制台模式时遇到错误:

$MethodDefinitions = @'
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
'@
$Kernel32 = Add-Type -MemberDefinition $MethodDefinitions -Name 'Kernel32' -Namespace 'Win32' -PassThru
$hConsoleHandle = $Kernel32::GetStdHandle(-11) # STD_OUTPUT_HANDLE 
$lpMode = 0
$Kernel32::GetConsoleMode($hConsoleHandle, $lpMode)

但是我收到以下警告和错误:

WARNING: The generated type defines no public methods or properties.
Method invocation failed because [Win32.Kernel32] does not contain a method named 'GetStdHandle'.
At C:\Users\John\get_console_mode.ps1:8 char:1
+ $hConsoleHandle = $Kernel32::GetStdHandle(-11) # STD_OUTPUT_HANDLE
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

Method invocation failed because [Win32.Kernel32] does not contain a method named 'GetConsoleMode'.
At C:\Users\John\get_console_mode.ps1:10 char:1
+ $Kernel32::GetConsoleMode($hConsoleHandle, $lpMode)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

知道我做错了什么吗?

更新:根据已接受的答案,这里是更正后的代码:

$MethodDefinitions = @'
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
'@
$Kernel32 = Add-Type -MemberDefinition $MethodDefinitions -Name 'Kernel32' -Namespace 'Win32' -PassThru
$hConsoleHandle = $Kernel32::GetStdHandle(-11) # STD_OUTPUT_HANDLE 
$mode = 0
$Kernel32::GetConsoleMode($hConsoleHandle, [ref]$mode)
windows powershell pinvoke
2个回答
5
投票

尝试使用以下方法定义(我刚刚添加了公共访问修饰符)

$MethodDefinitions = @'
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
'@

0
投票

我将用这个例子补充这里的解决方案。

每个人都可以按照自己的方式实现参数的传递,比如传递一个模式名称,也可以设置 禁用/启用/反转/检查

$MethodDefinitions = @'
  [DllImport("kernel32.dll", SetLastError = true)]
  public static extern IntPtr GetStdHandle(int nStdHandle);
  [DllImport("kernel32.dll", SetLastError = true)]
  public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
  [DllImport("kernel32.dll", SetLastError = true)]
  public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint lpMode);

  public const int STD_INPUT_HANDLE  = -10;
  public const int STD_OUTPUT_HANDLE = -11;

  public const int  ENABLE_PROCESSED_INPUT            = 0x0001;
  public const int  ENABLE_PROCESSED_OUTPUT            = 0x0001;
  '@

  $WinAPI = Add-Type -MemberDefinition $MethodDefinitions -Name 'WinAPI' -Namespace 'Win32' -PassThru
  $hConsoleHandle = $WinAPI::GetStdHandle($WinAPI::STD_INPUT_HANDLE)
  $mode=$WinAPI::ENABLE_PROCESSED_INPUT
  $WinAPI::GetConsoleMode($hConsoleHandle, [ref]$mode)

  if($true){
      # disable
      $dmi = -bnot $WinAPI::ENABLE_PROCESSED_INPUT
      $mode = $mode -band $dmi
  } else {
      #enable
      $dmi = $WinAPI::ENABLE_PROCESSED_INPUT
      $mode = $mode -bor $dmi
  }
  # inversion - enabled or disabled
  # $mode = $mode -bxor $WinAPI::ENABLE_PROCESSED_INPUT  

  # check 
  $mode -eq ($mode -bor $WinAPI::ENABLE_PROCESSED_INPUT) 

  $WinAPI::SetConsoleMode($hConsoleHandle, $mode)
© www.soinside.com 2019 - 2024. All rights reserved.