调用Runtime.InteropServices.DllImportAttribute

问题描述

编者注:该问题最终涉及如何使用.NET P / Invoke功能从PowerShell调用Windows API函数,例如SetForegroundWindow

$dll=[Runtime.InteropServices.DllImportAttribute]::new("user32.dll")
$dll.EntryPoint='SetForegroundWindow'
$dll.CharSet=1
$dll.ExactSpelling=$true
$dll.SetLastError=$false
$dll.PreserveSig=$true
$dll.CallingConvention=1
$dll.BestFitMapping=$false
$dll.ThrowOnUnmappableChar=$false
$dll.Invoke(
    #...
    #...    
)

如何完成此代码?我不理解“ 调用”中的参数。据我了解,其中之一是我的 EntryPoint (HWND)?

解决方法

System.Runtime.InteropServices.DllImportAttribute属性:

  • 通常以声明方式使用 ...

  • ... 装饰一个.NET方法,该方法的签名与正在调用的非托管函数相匹配。

通过这种方式定义.NET方法,您可以通过.NET功能调用 unmanaged (本机)函数,即,不是为.NET编写的DLL中的函数,例如Windows API函数。称为P/Invoke (Platform Invocation Services)

您不能直接在PowerShell代码中执行此操作,但是可以将Add-Type cmdlet与-MemberDefinition参数一起使用来按需编译C#代码。 -MemberDefinition自动导入System.Runtime.InteropServices名称空间,并在以-Name参数命名的命名空间中自动将传递给它的方法定义包装在以-Namespace参数命名的类中。

Add-Type -Namespace Util -Name WinApi -MemberDefinition @'
  [DllImport("user32.dll",SetLastError=true)]
  public static extern bool SetForegroundWindow(IntPtr hWnd);
'@

$hwnd = ... # determine the handle of the target window.

# Now call the unmanaged function.
[Util.WinApi]::SetForegroundWindow($hwnd)
  • 请注意声明性地使用DllImportAttribute(在这种情况下,后缀Attribute是可选的),并且只有源DLL名称是 required 所必需的,以构造实例为各种属性(例如上述SetLastError)提供值是可选

  • 要修饰的方法-您将能够从PowerShell代码中调用的方法-必须声明为public static extern,其余的方法签名必须与返回类型和set匹配。调用的非托管DLL函数的参数,包括其类型。

    • 默认情况下,假定非托管函数与该方法具有相同的名称,尽管您可以使用不同的名称命名该方法,并使用{{1}的EntryPoint属性指定要显式调用的函数的名称}。
  • 网站pinvoke.net是查找Windows API函数(例如手头SetForegroundWindow函数)的预定义定义的有用资源。