Exercise 4: Managed Code from PowerShell v2 (Background)

Figure 1

You may have a folder full of useful little C# applications. Maybe you want to run a quick test of .Net code and you don’t have Visual Studio handy; or maybe you want to find out if your script would be faster if you wrote part of it in C#, but it’s just not worth the hassle of compiling a DLL and loading it. Whatever the case might be, you might be interested in writing managed code into your PowerShell scripts; and always keep in mind that PowerShell’s main goal is to make things easier. If it can save you a couple of minutes, it’s worth it.

For this reason, PowerShell V2 introduces Add-Type. The Add-Type cmdlet lets you define a .NET class in your Windows PowerShell session. You can then instantiate objects (by using the New-Object cmdlet) and use the objects, just as you would use any .NET object. If you add an Add-Type command to your Windows PowerShell profile, the class will be available in all Windows PowerShell sessions.

Figure 2

You can specify the type by specifying an existing assembly or source code files, or you can specify source code in line or saved in a variable. If you are familiar with PowerShell V1, you have probably loaded assemblies in the past using .Net libraries. Add-Type can also replace all the [Reflection.Assembly]::Load* methods so you can save some typing and it will be more readable and easier to remember. So, instead of:

PowerShell

[Reflection.Assembly]::LoadWithPartialName("System.Xml")

You can just use:

PowerShell

Add-Type –Assembly System.Xml

You can even specify only a method and Add-Type will define and generate the class. You can use this feature to make Platform Invoke (P/Invoke) calls to unmanaged functions in Windows PowerShell. For example, you could write a function that minimizes the CLI in PowerShell:

PowerShell

Function Minimize-ActiveWindow() { $signature = @" [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); "@ $showWindowAsync = Add-Type -memberDefinition $signature -name "Win32ShowWindowAsync" -namespace Win32Functions -passThru $showWindowAsync::ShowWindowAsync((Get-Process -id $pid).MainWindowHandle, 2) }

If you specify source code, Add-Type compiles the specified source code and generates an in-memory assembly that contains the new .NET types.

You can use the parameters of Add-Type to specify an alternate language and compiler (CSharp is the default). The languages are: Csharp, CsharpVerison3, VisualBasic, and Jscript.

Other parameters will let you specify compiler options, assembly dependencies, the class namespace, and the names of the type and the resulting assembly.

For example you can even compile into an executable console application. The following code generates a Hello World console application from C# code:

PowerShell

Add-Type -OutputType ConsoleApplication -OutputAssembly HelloWorld.exe @" using System; public class MyProgram { public static void Main(string[] args) { Console.WriteLine("Hello World"); } } "@

The Add-Type cmd offers massive flexibility on multiple reflection aspects that were not properly built into PowerShell V1. In the past you had to call .Net APIs to reach these results. Add-Type makes the task easier.