Wednesday, August 3, 2011

PowerShell Scripts and Cmdlets - Part 2

In my last post I talked briefly about my introduction to the world of PowerShell and outlined my plan for learning it. When I'm learning a new programming language or working in a new environment, I find it works well to have a real problem I'm trying to solve and then use that as the impetus to learn the language. That's why I picked the Unix "touch" command for my first cmdlet. There is no analogous cmdlet in PowerShell and it was something I wish I had when I was writing my first couple of PowerShell scripts.

In this post I want to dig a little deeper into how I implemented my touch-item cmdlet. I decided to use VisualStudio 2010, since it's the most recent release of VS as of now. I think prior versions of VS will work just as well, and most of this discussion will still be relevant if you are using VS 2008, 2005, etc.

Step 1 - Prerequisites
When starting out, you will need (of course) a version of Visual Studio and PowerShell installed. PowerShell might already be installed, depending upon the version of Windows you're running. But if not, you will need to install it. I'm using PowerShell 2.0 for this example. To access the PowerShell types in System.Management.Automation, you need to add a reference to System.Management.Automation in your project file. There are multiple ways of doing this. I learned after the fact that you can just edit your .csproj file directly and add a line like this:

<Reference Include="System.Management.Automation" />

This is much easier than what I did. If I remember correctly, I installed the PowerShell SDK and then added the reference via the VS UI as you typically would. I had to browse for it, though. It didn't appear in the .NET tab in the Add Reference dialog. The path to the assembly is:

[program files]\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll

Step 2 - Create the Class
When you create your Visual Studio project, you should create a class library. Once you have created your project and added the reference to System.Management.Automation, you can create a class file that will contain the code for your cmdlet. To avoid too much typing, I added a using System.Management.Automation statement to access the types without having to type the namespace every time.

Your class should inherit from one of the PowerShell cmdlet base classes - Cmdlet or PSCmdlet. The class must be public. And the class must be decorated with the Cmdlet attribute. The Cmdlet attribute specifies the verb-noun name of the cmdlet. The MS documentation states you should only use approved verbs. I broke that rule since "Touch" is not an approved verb (oh well). In all, your class declaration should appear as follows:

[Cmdlet("Set", "CoolnessLevel")]
class SetCoolnessLevelCommand : Cmdlet
{
... code goes here
}

You should now have a project that compiles. At this point, you are ready to start writing some actual code to do something interesting, which will be the topic of my next post.

If you can't wait until then, MSDN has some really good documentation on writing PowerShell cmdlets.



Monday, July 25, 2011

PowerShell Scripts and Cmdlets - Part 1

I have to admit I am a newcomer to PowerShell - definitely late to the party, and probably not fashionably late, either. But I decided to dig into it since I had to write a PS script as part of a project at work. And after that I decided I wouldn't just leave it at that, but use this as an opportunity to pick up another platform to add to my resume. So I wrote out a list of things I want to learn and am picking them off one by one.

1. Write a script
2. Write a cmdlet
3. Write a script using Exchange Management shell
4. Write a script that uses the SharePoint object model
5. Write a script that interacts with AD, WMI, other?

The first thing on my list is writing a PS script. I wrote a script to move files off of various servers onto a central server into a structured hierarchy of folders. The script employed some interesting bits, like an XML configuration file, command-line syntax help, working with files and directories and even displaying progress via the Write-Progress cmdlet. Nothing overly complicated, but it was a good way to get introduced to PS. I also wrote a script to create test data to test my script. In writing that script, I discovered that PS has no cmdlet akin to the Unix touch command. Segue into my next task.

For my cmdlet task, I decided to write a command that can update the last modified timestamp of a file or group of files. My idea is to have this follow the conventions of the Unix touch command. Except for the name. Powershell has it's own naming convention that uses a verb-noun pair for naming commands. To stick with this convention, I decided to go with "touch-item" as the name of my cmdlet.

I won't go into the minute details of how you write a cmdlet, but the basics are you create a class that inherits the Cmdlet class, add an attribute specific to Powershell that defines the name of the cmdlet (i.e. touch-item, in my case), and then override some methods to provide the cmdlet's processing. For my development environment, I decided to use VisualStudio 2010 and targeting the .NET Framework 3.5.