[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.UnsafeNativeMethods
是System.Windows.Forms
程序集中的私有类型,因此您不应该依赖它-不能保证它会继续存在(或者至少使用此特定名称和/或签名存在(。 -
通常情况下,您不希望加载与应用程序用途无关的程序集,因为它们恰好包含Windows API包装方法。
因此,请考虑通过Add-Type -MemberDefinition
定义您自己的Windows API包装方法,如本回答中所述。