After my previous post of some snippets from my PowerShell profile; I received another email from the person that prompted me to write that post, asking some questions about calling Windows APIs from PowerShell. It turns out that this isn’t so straight-forward, despite PowerShell’s pitch as a system automation language!

The confusion came from various varying samples online of how to do this in PowerShell; and they all used blocks of C#, which many PowerShell users aren’t particularly familiar with.

Although I couldn’t find a way to do this without the C# wrapper, I did think it was worthwhile extracting some parts out of the C# code to avoid having to manipulate so much C# code in a quoted string inside PowerShell to add new Windows API methods. Unfortunately the argument types still need to be in C#, because I don’t know how to map them from the C++ examples easily.

It’s very basic; and can probably be improved by anyone that has some knowledge of calling Windows APIs; but hopefully it’s a little simpler if you’re less comfortable with C#.

In PowerShell profile:

# Helper functions for building the class $ script : nativeMethods = @(); function Register-NativeMethod ([ string ] $dll , [ string ] $methodSignature ) { $ script : nativeMethods += [ PSCustomObject ]@{ Dll = $dll ; Signature = $methodSignature ; } } function Add-NativeMethods () { $nativeMethodsCode = $ script : nativeMethods | % { " [DllImport( `" $( $_ . Dll ) ` ")] public static extern $( $_ . Signature ); " } Add-Type @" using System ; using System.Runtime.InteropServices ; public static class NativeMethods { $nativeMethodsCode } "@ } # Add methods here Register-NativeMethod " user32.dll " " bool SetForegroundWindow ( IntPtr hWnd ) " Register-NativeMethod " user32.dll " " bool ShowWindowAsync ( IntPtr hWnd , int nCmdShow ) " # This builds the class and registers them (you can only do this one-per-session, as the type cannot be unloaded?) Add-NativeMethods

And to use them:

# (the Out-Null is just to throw away the return value) [ NativeMethods ]:: SetForegroundWindow (( Get-Process -name notepad ) . MainWindowHandle ) | Out-Null [ NativeMethods ]:: ShowWindowAsync (( Get-Process -name notepad ) . MainWindowHandle , 2 ) | Out-Null

Hopefully this helps a little. If anyone can suggest improvements (being able to paste method signatures directly from the documentation would be good), I’ll update the post.