Learn about Windows PowerShell
Summary: Microsoft Scripting Guy, Ed Wilson, talks about the need to use .NET Framework classes from within Windows PowerShell code.
Microsoft Scripting Guy, Ed Wilson, is here. The Scripting Wife and I had a great meeting with the Windows PowerShell Users Group in Charlotte, North Carolina. It was a script club format, so there was no set agenda, nor was there a formal presentation. This provided a great chance to talk to people, find out what they were working on, and in general, have a lot of fun. Speaking of a lot of fun, make sure you check out the first ever Windows PowerShell Saturday that will be held in Columbus Ohio on March 10, 2012. This event, limited to 100 persons, is nearly sold out. So you need to hurry if you want to take advantage of a unique opportunity to network with a great bunch of Windows PowerShell people. The Scripting Wife and I will be there, as will an all-star group of other Windows PowerShell luminaries.
One of the questions I had from a group member was about using the .NET Framework from within Windows PowerShell. I have written quite a bit about using .NET Framework classes from within Windows PowerShell. Those blogs cover working with methods, discovering properties, finding documentation, and other bread-and-butter types of issues.
One of the things that I have not talked much about is why one needs to use .NET Framework classes inside of Windows PowerShell. Keep in mind, that as a best practice, I recommend using a native Windows PowerShell cmdlet when it exists—unless there are compelling reasons for not doing so. For example, I have seen a number of Windows PowerShell scripts (for example, when I was grading the Scripting Games submissions for the last three years), where participants use .NET Framework classes when there is a perfectly good Windows PowerShell option available. Here are two equivalent commands:
In the image that follows, I run both commands, and you can see that the output is essentially the same. (That the time indicated is three seconds later is a feature of the fact that for some reason it took me three seconds to run the second command.)
I can use the GetType method to verify that both commands return a System.Datetime object. These two commands are shown here.
PS C:\> ([datetime]::now).gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True DateTime System.ValueType
PS C:\> (Get-Date).gettype()
Because both commands return a DateTime .NET Framework class object, there is no advantage to the first command. Some may ask, what does the first command actually do? The command that appears here calls the static DateTime.Now property from the System.DateTime .NET Framework class.
The static Now property returns a System.DateTime object that represents the current local date and time—this is the same thing that the Get-Date cmdlet does. The difference? Well, the command Get-Date is much easier to read than [datetime]::now. So why do people use the static Now property? Well, I am convinced there are two reasons.
The first reason, I feel is legitimate: .NET developers may not know that the Get-Date cmdlet exists, and they have learned that to call a static member, they put the class name in square brackets and use the double colon before the member name. As I said, this is completely legitimate. Windows PowerShell is flexible enough, that you can write Windows PowerShell code as if it were C#, VB.NET, or even as if it were VBScript or Perl. Anything that helps you get the job done is fine with me—after all, Windows PowerShell is simply a tool for the vast majority of network administrators.
The second reason is more insidious. I think there are some people who simply want to use .NET Framework classes because they think it is cool, and that it makes the code appear to be more complex. Maybe they are attempting to impress their coworkers or their boss. Maybe they think that if people see things like Get-Date in a Windows PowerShell script, they will realize how easy Windows PowerShell is to use and to learn, and then they will no longer have the mantle as the “PowerShell guru.” I am all for job security, but I prefer to ensure job security by helping others maximize their potential. I prefer to show people how easy it is to use Windows PowerShell to become more productive than to attempt to obscure that fact by deliberately writing confusing code.
What do you think? I would love to hear from you.
Tomorrow I will discuss those occasions when I think it is OK to use .NET Framework code. There are times when it makes perfectly good sense.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at email@example.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
@jrv: I totally agree there are best practices, I also agree that one way is better, slightly or significantly, than the other from technical perspective; but I just don't see how it would relate to the conclusion that someone tried to make his/her script look cool, or job security discussion etc.
Why not just keep technical discussion to technical?
I was not really considering off-point 'noisy' issues such as job security.
Issues of performance, understandability, portability and conformance to standards, both global and corporate, are what i believe are important areas of discussion. Perhaps there are other areas that should be included as well.
Job security is about an individual employee and has no bearing here.
We can re-interpret 'look cool' to be the readability of a script. To that point I offer the Verb-Noun nature of CmdLets as one good reason to use them over the Net Classes direct method.
In simple everyday scripts I suggest whatever gets the job done without damage to the system s being acceptable. For scripts that are to be shared a nit more discipline may be called for.
I would suggest doing what we have always done in programming when calling a foreign API; encapsulate it.
This can be included in a library module and will allow us to modify its behavior. We can also replace it easily if newer functionality becomes available by just editing one location. The designers of PowerShell have given us the tools to support nearly all standard modes of program design and support. PowerShell is not a second class scripting language. It is a full first class language that supports command line ad-hoc tools and batch scripts along with the ability to be easily extended in almost any direction.
To me there is a third option: performance.
When I run both commands with measure-command the static .Net call is 2x-3x faster on my machine. May not seem like much, but to a developer-minded person that could be the tipping of the scales in favor of using .Net vs. native PowerShell commands. Many times when I'm teaching PowerShell workshops I show an example of adding numbers 1 to 10,000 to an array using native PowerShell array vs. .Net generic list. The .Net way is typically 1000% faster than native PowerShell. Raises interesting questions and discussions.