Using .NET Framework Assemblies in Windows PowerShell

Using .NET Framework Assemblies in Windows PowerShell

  • Comments 8
  • Likes

Summary: Guest bloggers Microsoft PFEs Adam Haynes and Shubert Somer continue their .NET Framework Essentials post by talking about assemblies.

Microsoft Scripting Guy, Ed Wilson, is here. Today is part 4 of a 5-part series written by guest blogger Adam Haynes with help from his friend Shubert Somer. You will want to go back and read part 1, part 2, and part 3 (if you have not already done so) before you read today’s blog.  

Here’s Adam …

Shubert warned me about this “simple” blog post on .NET Framework Essentials. I am paraphrasing here, but it’s like getting too close to a black hole. Black holes are cool as is mixing .NET Framework and Windows PowerShell, but if you get close enough to have a peek over the edge, it’s too late and you’re getting sucked in. We tried to keep it simple, and so far, we have talked about: type/class, object, method, constructor, property, and members. While this is not an all-encompassing list of .NET terminology, we actually glossed over a rather important topic.

Remember when I said that in order for the script in the previous post to work you needed to have the Active Directory module available/installed? There is a very specific reason for this. The script did use several cmdlets that are part of the Active Directory module (installed with RSAT), but the part we glossed over was the System.DirectoryServices.ActiveDirectory assembly. Loading the Active Directory module into the Windows PowerShell console, loads the assembly for us.

I don’t want you to have to click back and forth between posts, so we are going to continue this post with a new sample to introduce this new concept and reiterate the previous learning. This script gives us access to Windows Forms objects. I know what you’re thinking. We spent all this time talking about how cool Windows PowerShell is and now I want you to go back to a GUI!? Well, not exactly, and here is why: while I love PowerShell, some users of the scripts I produce and assist with are a little gun shy when it comes to the blinking cursor in the deep blue box.

This little snippet pops open the dialog box we are all used to in the GUI when opening a file for input. It can be a nice thing to have if you are asking for files from the user, and they are not comfortable in the Shell (or if you are lazy like me).  

<SCRIPT >

 [reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
$openFile = New-Object System.Windows.Forms.OpenFileDialog
$openFile.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*"
If($openFile.ShowDialog() -eq "OK"
{get-content $openFile.FileName} 

</SCRIPT >

Image of script

Most of this should be familiar to you, but line 1 looks oddly familiar—odd in that I have no idea what reflection.assembly means, and familiar because it looks like a static method. Why is it important or necessary, you ask? Because this is what the script returns when we don’t use it.

Image of command output

It seems that Windows PowerShell doesn’t know about the OpenFileDialog constructor, for some reason. I thought PowerShell was all knowing and all seeing? I want to turn it back over to Shubert, because that one line of the script will consume most of this post. That one line will also allow you to reach into .NET Framework and access whatever Microsoft technology you are working with. 

Shubert: There is a lot going on with that one line, so naturally I want to give some background to put it in to context. The way we deliver modular code, that is, code that has a chunk of functionality that can be reused, is to package stuff into DLLs (DLL stands for Dynamic Link Library, which is code that can be loaded into memory and executed on-demand). Back in the pre-.NET days, I liked to compare Windows programs to a bucket of marbles, with each marble representing a DLL. Installing a program was like emptying the bucket into your basement, and uninstalling was like telling one of your kids to go down in the basement and pick up all the green marbles. Keeping track of all the marbles was something known as DLL Hell.

Enter .NET … instead of a bucket of marbles, .NET Framework is more like having a bag of marbles with a little “contents” label. Installing a .NET program is more like putting the bag of marbles in a bag of marbles shelf in your basement, where you keep everything in alphabetical order. Mostly.

“Gee, that doesn’t sound much better,” you may think, but actually it is. It’s easier to find the bag of marbles you are looking for, and the label tells you which marbles are inside and what they do. The bags of marbles are like .NET assemblies, and the label on the bag is what reflection is for .NET Framework.

Like all things in .NET, reflection is actually just another set of .NET objects, and so they have their own sets of properties and methods. Because they are mostly utility-like things, many of these are static. The .NET technical term for reflection is a namespace, and it is very important to understand the difference between a namespace, an assembly, and a class.

Namespaces are just labels that are used to allow classes from different assemblies to have the same name and not interfere with each other. Much like classes form a container, or boundary, for their members (so many different classes can have an “Open()” method, for example), namespaces form a container for classes with the same name. Native .NET namespaces start with “System” (this is the root of the .NET namespace universe). The convention for application-specific namespaces is to start them with {CompanyName}.{ProductName}. So, for example, you may see Microsoft.Office.{some more stuff} for Office-related classes.

An assembly is a packaged chunk of functionality (the .NET equivalent of a DLL). Almost universally an assembly will consist of exactly one file (either a DLL or an EXE). To make things confusing, the naming convention for assemblies is very similar to the naming convention for namespaces. Be warned: they are not the same thing! An assembly may contain classes from many namespaces, and a namespace may cover many assemblies. Although not strictly correct, you can think of the assembly as the physical file containing the executable code and a namespace as a category to organize all the code that relates to a particular area.

So now, this line might start to make sense. Reflection is the namespace that tells Windows PowerShell exactly which assembly class to use (the full namespace is “System.Reflection”, but the left-most parts of the namespace can be dropped as long as it does not lead to any ambiguity—if it does, then Windows PowerShell should complain with some kind of “unable to resolve object path” message). The assembly class has a bunch of static methods for handling assemblies. We are using the method that will load the desired assembly (some file on disk) into memory so that it can be accessed by Windows PowerShell. To use the marbles analogy, you are telling one of your kids to go in the basement and bring back the “System.Windows.Forms” bag of marbles so that you can play marbles with them.

You will see later in the code that System.Windows.Forms is also a namespace, and that can make things a little confusing. If you are looking in MSDN for how to load the assembly that you need to access that cool class you found, check for the assembly name—it may be different (sometimes much different) from the class namespace!

Image of SPFarm class content

MSDN Reference: http://msdn.microsoft.com/en-us/library/ms973231.aspx

Adam: Well, I have to say that after listening to that in person, I was less smart than before we talked. After reading that a few times, I think it has sunk in. In the example from part 1 of the series, we didn’t need any if this because the Import-Module cmdlet did this work for us. The developers that wrote the module knew they needed the DirectoryServices namespace, so the Active Directory module has this type of code in it, and we don’t have to deal with it as administrators.

Now that we know why line 1 is so important, you might ask why we talked about it at the end? Well, if we started with that, do you know many admins that would have read this far? J I know that when Shubert tried to start out teaching me that one, I was reaching for the fake phone call to bail. We are almost done. In the final post, we will take this new-found knowledge and apply it line by line to the script we introduced in this post. 

~Adam

Thank you, Adam and Shubert. I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Is there any particular reason why you've used [reflection.assembly]::loadwithpartialname("system.windows.forms") instead of Add-Type -AssemblyName System.Windows.Forms?

    Note: Readers who use PowerShell ISE to run your code won't see the error, because PowerShell ISE is loading the System.Windows.Forms assembly by default. You might add a note that powershell.exe and powershell_ise.exe don't provide the same assemblies by default.

  • I have to echo Aleksandar's concern here, as an "expert" here, should not the blogger know LoadWithPartitialName is long considered as depreciated?

    To be honest, this series of blog brings me more confusion than value, esp. when I read in the previous blog (part 2) that said "Powershell is object oriented", so when does PS become an OO language? can it create a new class itself? or maybe I know too little (quite possible of course)

  • @jeff yao – PowerShell has been object oriented since its inception. It is a scripting language not a development language so no we don’t create classes, we simply use existing classes to automate tasks. To work as an administrator, I don’t need any special development tools to gain access to the .Net framework. The lines are definitely blurred, but everything in PowerShell is an object. If there is anything specific I can clarify, please let me know.  

  • @Aleksandar Nikolić – Great point on loading the assembly. The goal of the series is to expose administrators to .Net. It was a good segue into reflection and I simply overlooked loadwithpartialname. Shubert worked up a change, so we will try to get the post updated soon.

  • @jeff yao

    Tell us what in POwerShell is NOT an object.  Everything in PowerShell is inherited from System, Microsoft or any other base class we choose to define.  Even a lowly 'int' is an object.

    Where is there any indication that htere are no objects.

  • @jeff yao

    I almost forgot.  Yes - we can create classes (types) in PowerShell.  NOw it is up to you  to figure out how we do this.

  • This was a very helpful post. Thank you.

  • After reading it's more confusing specially not sample to explan each terms you use, like assembly, namespace, convention that should be used. I'm a beginner and i don't understand how your explanation can help me to find for exemple what mean this part of code $expression = new-object Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.Expression -ArgumentList $arg.
    I try in google this to seahc about Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.Expression coz i need to understand what is this object, what is contructor and propety and methods but i found nothing exept some samples :(. Waht is it an assembly ? for me it's an object so mean there is a Class definition somewhere, but where found those information. Hope you Understand what i mean.
    Sorry if i may be in a wring forum but it's 2 days i seach on internet to understand sample i found to make automatic thing for SCCM2012 and the only documentation in MSDN is too poor or not exist.