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

I found this code. It works. My question is how i can find where is function stored?

Image, that I want to use the GetAsyncKeyState method without knowing about the code above: How can I find out what type in what assembly provides this method?

May be there is some function like:

function Get-win32FunctionLocation($fName){
    #...
}

Get-win32FunctionLocation 'GetAsyncKeyState'

<#Output:

    location  : [Windows.Forms.Form]
    TypeName  : System.Windows.Forms.UnsafeNativeMethods

#>

Or may be some other source of this information...

P.S. I know about Add-Type, but my interest is in this code.

0

3 Answers 3

2

You can enumerate all types in all already-loaded assemblies like so:

$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 will now contain any public methods named GetAsyncKeyState

Sign up to request clarification or add additional context in comments.

2 Comments

Supplement: $targetMethod.ToString() to see the signature or $targetMethod.GetParameters() to get additional information about the parameters.
That's a helpful technique in general, but note that .GetTypes() also includes non-public types. While this is necessary in the OP's case, because the System.Windows.Forms.UnsafeNativeMethods is private, it's worth pointing out that relying on private types is ill-advised. Also, I've noticed that .GetTypes() can seemingly report types multiple times, and doesn't include forwarded types; to get all distinct public ones: [AppDomain]::CurrentDomain.GetAssemblies() | % { $_.GetTypes() + $_.GetForwardedTypes() } | ? IsPublic | Sort-Object -Unique FullName, { $_.Assembly.Location }
2

There is no universal solution to this problem. Most people that rely on Win32 functions in .NET environments use pinvoke.net to lookup functions/members, copy the C# signature and Add-Type them in PowerShell as described here.

$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

The namespace part can be tricky because sometimes it's not just the function but also the parameter that requires us to add additional namespaces and references; sometimes those are listed on pinvoke.net sometimes not and you only find out when you invoke the function and get an error like

The type or namespace name 'Forms' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?)

Then, you have to look them up in the MSDN or run a web search like "GetAsyncKeyState site:learn.microsoft.com" to Add-Type -AssemblyName .. references as needed.

I think it does not get much better since Microsoft is not interested in making the Win32 more accessible; en contraire.

Comments

1

I suggest rethinking your approach:

  • System.Windows.Forms.UnsafeNativeMethods is a private type inside the System.Windows.Forms assembly, so you shouldn't rely on it - there's no guarantee that it will continue to exist (or at least exist with this particular name and/or signature).

  • You generally don't want to incur the overhead of loading assemblies that are unrelated to your application's purpose, just because they happen to contain Windows API wrapper methods.

Therefore, consider defining your own Windows API wrapper methods via
Add-Type -MemberDefinition
, as detailed in this answer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.