Powershell反射查找功能


[Windows.Forms.Form].
Assembly.GetType(
'System.Windows.Forms.UnsafeNativeMethods'
).GetMethod('GetAsyncKeyState').Invoke($null,
@(
0x09 # Tab key code
)
)

我找到了这个代码。它有效。我的问题是如何找到函数存储在哪里?

图片,我想在不知道上面代码的情况下使用GetAsyncKeyState方法:我如何才能找出在什么程序集中提供此方法的类型?

可能有一些功能,比如:

function Get-win32FunctionLocation($fName){
#...
}
Get-win32FunctionLocation 'GetAsyncKeyState'
<#Output:
location  : [Windows.Forms.Form]
TypeName  : System.Windows.Forms.UnsafeNativeMethods
#>

或者可能是这些信息的其他来源。。。

p.S。我知道Add-Type,但我感兴趣的是这个代码。

您可以枚举所有已加载程序集中的所有类型,如下所示:

$methodName = 'GetAsyncKeyState'
$appDomain   = [System.AppDomain]::CurrentDomain
$assemblies  = $appDomain.GetAssemblies()
$allTypes    = $assemblies.GetTypes()
$allMethods  = $allTypes.GetMethods([System.Reflection.BindingFlags]'Static,Instance,Public')
$targetMethods = $allMethods.Where({$_.Name -eq $methodName})

$targetMethods现在将包含任何名为GetAsyncKeyState的公共方法

这个问题没有通用的解决方案。大多数在.NET环境中依赖Win32函数的人都使用pinvoke.NET来查找函数/成员,复制C#签名并在PowerShell中添加类型,如下所述。

$Signature = '[DllImport("user32.dll")]public static extern short GetAsyncKeyState(int vKey);'
Add-Type -MemberDefinition $Signature -Name 'Win32GetAsyncKeyState' -Namespace Win32Functions #-PassThru
Add-Type -AssemblyName System.Windows.Forms 
[Win32Functions.Win32GetAsyncKeyState]::GetAsyncKeyState([Windows.Forms.Keys]::0x09) # Tab key code

名称空间部分可能很棘手,因为有时不仅是函数,还有参数需要我们添加额外的名称空间和引用;有时这些在pinvoke.net上列出,有时没有,只有当你调用该函数并得到类似的错误时,你才会发现

命名空间中不存在类型或命名空间名称"Forms"System.Windows"(是否缺少程序集引用?(

然后,您必须在MSDN中查找它们,或者运行类似";CCD_ 5";根据需要将CCD_ 6引用。

我认为它并没有变得更好,因为微软对让Win32更容易访问不感兴趣;相反。

我建议重新思考您的方法:

  • System.Windows.Forms.UnsafeNativeMethodsSystem.Windows.Forms程序集中的私有类型,因此您不应该依赖它-不能保证它会继续存在(或者至少使用此特定名称和/或签名存在(。

  • 通常情况下,您不希望加载与应用程序用途无关的程序集,因为它们恰好包含Windows API包装方法。

因此,请考虑通过
Add-Type -MemberDefinition
定义您自己的Windows API包装方法,如本回答中所述。

最新更新