My blog here at code4ward isn’t quite active lately. My local community engagements at expertslive.at are consuming most of my time. But I had the opportunity to speak at the Experts Live EU event in Berlin and thought, this would be a good opportunity to share my slides and code from my talk on my code4ward blog.
My talk is about how to interop with other technologies and APIs from PowerShell. PowerShell provides access to .NET framework classes and types, COM interop and even (using .NET) gain access to the Win32 API. This makes PowerShell very POWERFUL (pun intended!).
Download all the samples and the slides here: PowerShell Interop Samples.
To illustrate what you can do and how you can do it, I provided a couple of samples with code and comments:
1. Visual Studio
This is just a small c# WinForms project to demonstrate what code the designer generates when a UI is built. This will be used in the next sample code.
2. PowerShell WinForms
In this directory, you’ll find two PowerShell scripts. The first one (SimpleWinFormsApp.ps1) is basically a “translation” of the c# code to PowerShell.
# tell PowerShell that we want to use classes from System.Windows.Forms assembly
Add-Type -AssemblyName System.Windows.Forms
# create a new form
$Form = New-Object System.Windows.Forms.Form
# create and setup the listbox
$ListBox = New-Object System.Windows.Forms.ListBox
$ListBox.Dock = [System.Windows.Forms.DockStyle]::Fill
$ListBox.Items.Add("Europe") | Out-Null
$ListBox.Items.Add("Switzerland") | Out-Null
$ListBox.Items.Add("Austria") | Out-Null
# create and setup the button
$Button = New-Object System.Windows.Forms.Button
$Button.Dock = [System.Windows.Forms.DockStyle]::Bottom
$Button.Text = "Click Me!"
$Button.Add_Click({ [System.Windows.MessageBox]::Show($ListBox.SelectedItem) })
# add listbox and button to the form
$Form.Controls.Add($ListBox)
$Form.Controls.Add($Button)
# show the form
$Form.ShowDialog()
This code above is basically the same code as generated by the c# WinForms Visual Studio project mentioned above.
Note the Add-Type cmdlet at the beginning of the script. This instructs PowerShell to load the Assembly “System.Windows.Forms” (from the Assembly Cache) which provides all the classes we need here, like forms, buttons, listboxes, etc.
Also in this directory, you will find a second approach (SimpleWinFormsApp-Alt.ps1) to do small UI projects in PowerShell. In this example, we are actually using the Add-Type cmdlet to basically compile and use the whole c# class as created by the WinForms Visual Studio project.
3. Keepass
To demonstrate, that not only built-in (or shipped) .NET framework classes can be used, this demo shows how to use any .NET assembly (which can be a DLL or even a EXE file written in .NET).
[Reflection.Assembly]::LoadFile($KeePassPath)
Note: You need to put all the KeePass files (including KeePass.exe) into the folder 03. KeePassKeePass in order to run the included code!
In this case we are using the LoadFile method of the Reflection.Assembly class to dynamically load an executable or DLL into our PowerShell runspace. After that, we have access to all types and classes defined in that assembly. The rest of the script deals with opening the database file and listing all saved credentials.
Since KeePass is open source, it’s quite easy to figure out how to access it. In case something is closed source or the source code is simply missing, you could still use reflection tools, such as JetBrains free dotPeek tool to get to the source. Needless to say that all copyrights should be respected here!
4. Extract Icon
This sample script demonstrates how to extract all frames (different sizes/color depths) in an icon file. The story behind this script is that I needed to extract those image files but I could only find c# based code which made use of WPF (System.Windows.Imaging) framework classes. It took me only a couple of minutes to “translate” / rewrite it to run as a PowerShell script.
5. Fun with COM
COM (Component Object Model) dates back to Windows 3.0, I think. So COM is actually a very old, but still a popular API to use and access “external” code or components.There are quite a few flavours of COM: COM+, DCOM (Distributed COM), ActiveX (mainly intended to embed UIs in web browsers), etc. A lot of 3rd party components, Microsoft Office and many of the system components (like Internet Explorer) are all exposed through COM APIs.
$excel = New-Object -ComObject Excel.Application
Using the New-Object cmdlet with -ComObject parameter to create a new “Excel.Application” instance, allows you to access all the power of Excel using code. This can be very handy to programmatically create reports or charts (as shown in the sample script).
The second sample is using Internet Explorer to open a web site and download all images through the downloaded document.
6. Win32 API
This is as deep as you can go. Accessing Win32 API or C/C++ functions from any DLL using pinvoke (Platform Invoke). The script shows how the SetWindowPos function from the user32.dll can be invoked using adding c# code. In this example, two processes are started and positioned on the screen at specific coordinates with specific dimensions. Of course, this is only the tip of the iceberg. Web sites like pinvoke.net provide access to many APIs with c# and VB.NET sample code and as shown in the sample code, it’s quite easy to use them from PowerShell as well.
Co-Founder and CEO of Royal Apps GmbH and Windows lead developer for Royal TS, a multi platform, multi protocol remote management solution, for Windows, macOS and mobile supporting RDP, VNC, SSH, Telnet, and many more.
Long time Microsoft MVP (2010-2020) supporting communities on- and offline as well as speaking at user groups and conferences about DevOps and other software development topics.