How To Load .NET Assemblies In A PowerShell Session

August 29, 2010

in .NET 4.0,.Net,Add-Type,C#,DLL,F#,JScript,PowerShell,VB.Net,Visual Basic

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:

image

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 }

Tweets that mention How To Load .NET Assemblies In A PowerShell Session -- Topsy.com
08.29.10 at 12:20 pm
progg.ru
09.02.10 at 4:12 am
Understanding .NET from the perspective of an IT Professional « Energized About Technology
05.28.11 at 1:38 pm
Gerando backups do SQL Server por PowerShell « SQL From Hell.com
01.12.12 at 7:27 am
Install a custom timer job in Powershell « Sharepoint…
01.22.12 at 7:32 am
AppSense Personalization API: Getting Started and Loading the Proxy DLL - String Theory
05.08.12 at 9:02 am

{ 10 comments… read them below or add one }

Holger 08.30.10 at 1:28 pm

Very nice article, thank you.

I was not aware of the Add-Type cmdlet, it’s pretty neat!

Klaus Graefensteiner 08.30.10 at 6:24 pm

I like to load assemblies using the Module manifest. The manifest loads dependent assemblies before you are using them in the module scripts.

Klaus

Doug Finke 08.31.10 at 7:38 am

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#.

Serendata 09.01.10 at 5:08 pm

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

Brad 12.09.11 at 12:57 am

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.

Doug Finke 12.09.11 at 9:51 am

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.

Brad 12.11.11 at 11:00 pm

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.

Peter Kriegel 05.03.12 at 6:19 am

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 ?

Doug Finke 05.03.12 at 8:21 am

Thanks Peter. Here is a start

[appdomain]::currentdomain.getassemblies()

Doug

Peter Kriegel 05.03.12 at 9:14 am

Fantastic ! Thank you again !

Leave a Comment

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Contrat Creative Commons

© 2007-2012, Doug Finke