Saturday, July 28, 2012

PowerShell: How to Manipulate Application Windows

So, I wanted to write a script to raise a window. Simple, right? As far as I can find, there is no way to manipulate external application windows in pure C#.

Ideally, there would be a method somewhere that would give me a list of System.Windows.Window objects, which would then allow me to manipulate them in various ways. But I can’t find one.

The best I could come up with in my searches was reference for Windows API functions for manipulating windows based on their handle:

http://msdn.microsoft.com/en-us/library/windows/desktop/ff468919(v=vs.85).aspx

This is actually pretty good, since maybe not all applications are PresentationFoundation windows and wouldn’t be associated with a Window object anyway.

So, the next problem was to call these functions from PowerShell.

In C#, calling a native function is done by attaching the [DllImport] attribute to an ‘extern’ function declaration. This actually makes things much easier, because PowerShell v2 can compile C# declarations on the fly using the add-type cmdlet.

So, here’s how to make the Win API methods available:

> $t = '[DllImport("user32.dll")] public static extern bool SetForegroundWindow(int handle);'
> add-type -name win -member $t -namespace native

Here’s how to get a window handle:

> ([diagnostics.process]::GetProcesses() | ?{ $_.ProcessName -eq "chrome" -and $_.MainWindowHandle -ne 0 }).MainWindowHandle
133226

And finally, here’s how to call the method using the window handle:

> [native.win]::SetForegroundWindow(133226)
True