繁体   English   中英

在 PowerShell 脚本中使用 Win32 GetStringTypeW()

[英]Using Win32 GetStringTypeW() in a PowerShell script

我想在 PowerShell 脚本中使用 Win32 GetStringTypeW()方法。

我在 C# 中找到了正确的签名,下面的代码在那里工作得很好:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern uint GetStringTypeW(uint dwInfoType, string lpSrcStr, int cchSrc, out ushort lpCharType);

private const uint CT_CTYPE1 = 0x0001;

public void MyMethod(string strIn) {
  ushort[] lpCharType = new ushort[strIn.Length];
  GetStringTypeW(CT_CTYPE1, strIn, strIn.Length, out lpCharType[0]);

  // Do stuff with lpCharType
}

lpCharType数组被 16 位无符号整数填充; 一个用于传入的字符串的每个字符。可以通过按位比较来检查整数,以找出字符串中存在哪些类型的字符。

我在 PowerShell 中将 C# 代码翻译成以下内容:

$MethodDefinition = @'
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern uint GetStringTypeW(uint dwInfoType, string lpSrcStr, int cchSrc, out ushort lpCharType);
'@

$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kernel32' -Namespace 'Win32' -PassThru

[System.UInt32] $CT_CTYPE1 = 0x0001

[System.UInt16[]] $lpCharType = [System.UInt16[]]::new($strIn.Length)

$Kernel32::GetStringTypeW($CT_CTYPE1, $strIn, $strIn.Length, [ref] $lpCharType[0])

# Do stuff with $lpCharType

这只是不会用任何东西填充$lpCharType ,并且根据我使用该代码的方式,我还可以完全用System.AccessViolationException: Attempted to read or write protected memory.

似乎 memory 中发生了一些我不完全理解的奇怪事情,那么有人对如何使其工作有任何建议吗?

注意:有趣的是,如果我尝试传入单个UInt16参数而不是它们的数组,它会填充一个正确的 integer 值,因此代码可以正常工作,但当然,它不能容纳多个值,这并不能解决访问冲突。

如果必须的话,我可以向$MethodDefinition添加中间方法 C# 以接受来自 PowerShell 的字符串,调用 GetStringTypeW(),并返回 output,但我希望尽可能避免使用 C# 代码填充我的 PowerShell 脚本.

正如zett42指出的那样,在 PowerShell 中,您无法获得对值类型数组的单个元素的引用,如本答案中所述。

但是,您可以简单地在 P/Invoke 声明中使用数组参数,并将数组作为一个整体从 PowerShell 传递:

$MethodDefinition = @'
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern uint GetStringTypeW(uint dwInfoType, 
                          string lpSrcStr, 
                          int cchSrc, 
                          ushort[] lpCharType); // Declared as array, w/o `out`
'@

$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kernel32' -Namespace 'Win32' -PassThru

[System.UInt32] $CT_CTYPE1 = 0x0001

$strIn = 'A!'

[uint16[]] $lpCharType = [uint16[]]::new($strIn.Length)

$ok = $Kernel32::GetStringTypeW($CT_CTYPE1, $strIn, -1, $lpCharType)

$lpCharType # -> 897, 528

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM