A PowerShell Cmdlet for Managing Windows Azure Diagnostics
I decided to write a PowerShell cmdlet to manage Windows Azure diagnostics. This cmdlet will let you retrieve and delete log information in the Azure cloud for your service; right now there isn’t any easy way to do this.
I started out by writing a simple spec for my tool; you can see it here. The spec just lets me flesh out some of the design issues before writing code.
I found that there is a PowerShell 2.0 SDK released a couple of months ago; I installed that.
Next, I fired up Visual Studio 2010 and looked for a template to create a PowerShell Cmdlet. Turns out there isn’t one. So you just create a class library; all there is to a PowerShell Cmdlet is an assembly that inherits from Cmdlet (or PSCmdlet).
I wnt to add a reference to System.Management.Automation as MSDN told me to. However, that doesn’t work. VS 2010 allows you to add a reference to System.Management, but not System.Management.Automation. After poking around a bit on the web, I found a post on Stack Overflow that provided the work-around.
I implemented a bunch of properties for my parameters and wrote a very simple ProcessRecord override just to make sure I was on the right track. I added a simple class that inherits from PSSnapIn (System.Configuration.Install) to provide the basic properties of the snap-in. The MSDN article referenced below does a good job of explaining this.
After doing this basic work, I wanted to install this as a PowerShell Cmdlet to make sure I’m on the right track. I built the Assembly in Visual Studio, and then started up PowerShell (which you can find in Start / Accessories / Windows PowerShell) and used a .NET tool called InstallUtil.exe to install the assembly so that PowerShell can find it. Note that you have to run PowerShell as Administrator for this install step to work – it doesn’t have to be running as Administrator to run the snap-in but to install it, it has to write to protected areas of the registry.
You can check that the snap in has installed using the PowerShell command “get-PSSnapIn” with the “-reg” flag to show you want the snap-ins that are registered:
However, there is a problem. When I try to add the snap-in to your PowerShell session, I get this error from PowerShell:
Add-PSSnapin : Cannot load Windows PowerShell snap-in AzureDiagnosticsSnapIn because of the following error: Could not load file or assembly 'file:///C:\users\Mike Kelly\Documents\Visual Studio 2010\Projects\AzureDiagnosticsCmdlet\AzureDiagnosticsCmdlet\bin\Debug\AzureDiagnosticsCmdlet.dll' or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.
At line:1 char:13
+ add-pssnapin <<<< AzureDiagnosticsSnapIn
+ CategoryInfo : InvalidArgument: (AzureDiagnosticsSnapIn:String) [Add-PSSnapin], PSSnapInException
+ FullyQualifiedErrorId : AddPSSnapInRead,Microsoft.PowerShell.Commands.AddPSSnapinCommandThere are two possible workarounds here:
- One is described on StackOverflow – it is to get PowerShell (and everything else) to run using .NET 4. I felt like this could cause other problems.
- The other workaround is to change the properties of the Cmdlet to require only .NET 3.5 instead of .NET 4. To do that, go to Visual Studio and right click on the Cmdlet solution. Select Properties and change “Target Framework” from “.NET Framework 4” to “.NET Framework 3.5”. OK the dialog telling you that the project must be closed and reopened. Then rebuild the Cmdlet and it will now work in PowerShell. Since I have no .NET 4 dependencies, this is an easier workaround for me.
Finally, I wanted to be able to debug the Cmdlet in Visual Studio. I found a posting here describing how to do this – but it didn’t work with the Visual Studio 2010 RC build I have. I have entered a bug against the RC on this.
So I rolled back to Visual Studio 2008, which I still have installed, and rebuilt the project there (because VS 2008 can’t read 2010 projects, I had to manually reconstruct the solution and project from the source files in VS 2008). In the process of doing this, I also found a post with (to me) simpler directions for debugging in Visual Studio. I am now happily debugging my Cmdlet in VS.