Recently I started toying with the idea of creating some of my own PowerShell cmdlets from scratch. I followed some MS documentation and soon had a basic version of “Get-Process” implemented, as well as my own “Stop-Process” cmdlet. Next in my sights is to create a few cmdlets that can interface with vSphere – ala PowerCLI. This is proving to be a little more difficult than I imagined, but I was able to create a basic cmdlet that could pump out some properties around the vCenter(s) connections by throwing the $global:DefaultVIServers VIServer[] array object into my custom cmdlet once a connection was made using PowerCLI. This wasn’t ideal though, as I want my cmdlet to “intercept” the current connection(s) made my PowerCLI, if any, otherwise to prompt the user to initiate a connection.

powershell cmdlet development

To get started I wanted to have some basic debugging capability available to allow me to inspect objects on the fly – this would help me determine what sorts of properties and methods are available on various objects, as well as providing me the ability to debug code easily – essential for any developer. In Visual Studio, this is normally a very easy task – just hit F5, or click the debug start button and away you go. With a cmdlet, you are essentially building an assembly (.dll file) from scratch, and you first of all need to load that into your environment and then debug from there.

I found this great post on amido.co.uk that explains how to debug normal PowerShell cmdlet development, but what about PowerCLI? Well a simple change can be made to get this to work. I have also made some modifications to my own pre-build build event settings in my PowerCLI Cmdlet project. These copy the built assembly into the PowerShell modules folder so that I can then load it using the Import-Module cmdlet.

First change I made to the amido blog settings was in my Command line arguments that are used when launching powershell.exe as an external program.


-NoExit -Command "& {add-pssnapin VMware.VimAutomation.Core; Import-Module ShoganPowerCLI}"

Firstly, I added a call to add-pssnapin – loading the PowerCLI snapin into the base powershell environment. Then I changed the add-pssnapin call to an Import-Module, loading my assembly (in this case called “ShoganPowerCLI”). This of course happens after the pre-build events, which I will explain next.

In your project’s properties (Alt-enter on the project name in the IDE), go to build events, and as per the amido blog post I linked above, use the following:

Pre-build event command line:


IF EXIST "$(TargetPath)" (%WinDir%\Microsoft.NET\Framework\v4.0.30319\installutil /uninstall "$(TargetPath)")

Post-build event command line:


cd $(ProjectDir)
del C:\Users\Shogan\Documents\windowspowershell\modules\$(ProjectName)\ShoganPowerCLI.dll
copy /y bin\debug\$(ProjectName).dll C:\Users\Shogan\Documents\windowspowershell\modules\$(ProjectName)\
%WinDir%\Microsoft.NET\Framework\v4.0.30319\installutil "$(TargetPath)"

Ensure your “Run the post-build event” option is set to “On successful build”.

pre and post build events for powershell cmdlet development

What this post-build event does, is it first of changes directory to your project folder. It then attempts to delete any older versions of the cmdlet assembly you may have from previous debug sessions (the del line). After this, it copies the debug version of your assembly .dll into a sub folder named after your project in the WindowsPowershell modules folder, attempting to overwrite any existing version if it is still there. After that, the last line is one from the amido blog post, running installutil.

Once this is all setup, compile and run your code in debug mode after setting a few breakpoints. Issue your custom cmdlet and watch in glee as the debugger halts on your breakpoint and allows you to inspect various objects/properties/etc…

P.S. if any of the PowerCLI dev team come across this post, I would love to get in touch to ask a few basic starting out questions 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *