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.

You may also like Chromebook Comparison Chart, Drone Comparison Chart and how to easily split Amazon referrals between Amazon US and Amazon UK.

Don't forget to check out my kids on YouTube! Amazon Echo Dot (2nd Generation) Review, GP Toys Luctan S912 RC Car Review, Syma X5HC-1 Drone/Quadcopter Review.