PowerShell is built on top of .NET. This allows you to tap into the power of the .NET framework as well as any DLLs/Assemblies you build. In version 2 of PowerShell the Add-type cmdlet was added which is the preferred way to load .NET assemblies.
In PowerShell Version 1 that cmdlet is not available so you need to use the one of the Load* static methods found in System.Reflection.Assembly.
| [Reflection.Assembly]::Load |
Loads an assembly |
| [Reflection.Assembly]::LoadFile | Loads the contents of an assembly file on the specified path |
| [Reflection.Assembly]::LoadFrom | Loads an assembly given its file name or path |
| [Reflection.Assembly]::LoadWithPartialName | Loads an assembly from the application directory or from the global assembly cache using a partial name |
Why?
For example, in PowerShell, if you want to encode a Url you can use the UrlEncode method found in the .NET HttpUtility Class.
If you fire up PowerShell and try to call the static method UrlEncode found in System.Web.HttpUtility you’ll get this error.
[System.Web.HttpUtility]::UrlEncode("this is a test")
Unable to find type [System.Web.HttpUtility]: make sure that the assembly containing this type is loaded.
You can solve this by loading the System.Web .NET assembly. This is equivalent to being in the Visual Studio IDE, adding a reference and then adding a using statement.
Using Reflection.Assembly in PowerShell Version 1
[Reflection.Assembly]::LoadFile( ` 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Web.dll')` | out-null [System.Web.HttpUtility]::UrlEncode("this is a test")
Using Add-Type in PowerShell Version 2
Add-Type -AssemblyName System.Web [System.Web.HttpUtility]::UrlEncode("this is a test")
Additional Reflection.Assembly usage
[void] [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") [reflection.assembly]::Load("mscorlib.dll") | Out-Null [void][system.reflection.assembly]::loadfrom("c:\windows\system32\inetsrv\microsoft.web.administration.dll")
Additional Add-Type usage
Add-Type -AssemblyName "System.Windows.Forms" Add-Type -AssemblyName "mscorlib.dll" Add-Type -Path "c:\windows\system32\inetsrv\microsoft.web.administration.dll"
Compiling C# on the fly in Version 2
Add-Type -TypeDefinition @" public class Test { public static int Add(int n1, int n2) { return n1 + n2; } } "@
If you change the signature of the Add method you will get this error:
When compiling code on the fly or loading assemblies they cannot be unloaded.
.NET assemblies can’t be unloaded from a session (it’s a .NET thing, not a PowerShell thing) therefore DLLs can’t be unloaded from a session. This means that you can’t update a DLLs once it’s been loaded. We can’t even update the assembly on disk because the file is locked when the assembly is loaded.
- Bruce Payette Windows PowerShell in Action, Second Edition
Another way to use the –Path parameter on Add-Type
You can point to a C# source code file directly.
Add-Type –Path c:\test\Hello.cs
Add-Type is not limited to compiling only C#
You can inline these languages using the –Language parameter CSharp, CSharpVersion3, VisualBasic, JScript.
Notice, F# is not supported. Here is a post How to add an F# type to a PowerShell session that inlines F#.
NOTE: This uses the F# DLLs shipped with .NET 4.0
Add-TypeFSharp -TypeDefinition @" module MyModule let Add a b = a + b;; "@ 1..10 | % { [MyModule]::Add( $_, $_*2 ) }
Finally
There are additional parameters that the Add-Type cmdlet supports. You can generate a DLL file for the assembly with the specified name in the location, specify compiler parameters, specify assemblies which your code depends on and use wild cards when loading assemblies.
Check out the online help for Add-Type.



{ 6 trackbacks }
{ 10 comments… read them below or add one }
Very nice article, thank you.
I was not aware of the Add-Type cmdlet, it’s pretty neat!
I like to load assemblies using the Module manifest. The manifest loads dependent assemblies before you are using them in the module scripts.
Klaus
Klaus, yes that is a good way to load assemblies too. This approach is for when you have stand-alone scripts or want to inline say C#.
Great post – thanks a lot!
I guess it’s time to review my old V1 scripts and replace all those LoadWithPartialName’s. It’s deprecated anyway.
Cheers!
Christiane
This is a great post! But leaves me with a question…
This sounds very stupid, but im trying to use a loaded assembly and cant find the correct syntax to use. Ive successfuly loaded the module’Wtsapi32′.
But im not sure how to call the function ‘WTSQueryUserToken’. Any hints/hints?
My goal with the script is to launch a new process as an existing user, into there specific session, using powershell.
Thanks for the question Brad. I haven’t played with wtsapi32. It may be a pinvoke issue. I don’t know off the top of my head. Toss this question onto Stackoverflow or Twitter with #powershell and we can get more eyes on it.
Found this on Stackoverflow, it may be what you’re looking for.
Thanks alot for your feedback! Ive submitted a query onto Stackoverflow. The link you posted unfortunatly didnt solve the issue. Here is a link to the logic im looking at implementing.
Hi Doug very goog Post! Thank you for that!
Do you know how i can list the currently loaded .Net assemblys to see which version of .NET is used by them ?
Thanks Peter. Here is a start
[appdomain]::currentdomain.getassemblies()
Doug
Fantastic ! Thank you again !