vRealize Orchestrator and Running PowerShell Commands inside VMs

I’ve had the chance to work with vRealize Orchestrator recently.  It’s got a bit of a learning curve, but we’re making good progress and are managing to automate some of those basic tasks that just seem to eat up time otherwise.  One of the challenges that we’ve come across is related to running PowerShell commands in the Guest OS itself (this is different than the PowerShell integration, which is a whole different ball of wax) via VMTools.  We ended up trying a bunch of different techniques, with various drawbacks and advantages.

The first thing that we tried was the “Run program in guest” workflow under vCenter -> Guest Operations -> Processes.  When you launch that workflow, you’ll need to provide several pieces of data: which VM you want to execute the application in, the credentials for that VM, the path to the program and any arguments that the program will need (as well as a few others that we didn’t use in this situation).  The VM and credentials part is self explanatory.  In order to run PowerShell commands, we had to specify the PowerShell executable itself: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe.  We had to get a bit creative with the arguments.

The first argument that we looked at was –command.  The PowerShell documentation lists the –command argument and gives some example syntax; the only form that I was able to get working was –command “& {<command>}”.  So, if I want to do a get-date, I can use powershell.exe –command “& {get-date}” and it will successfully run.  Notice that the whole cmdlet has to be in quotes that are being interpreted by a CMD prompt… this can make things get confusing.  What if you want to split a string?  In a PowerShell prompt, you can use “this is a string”.split(” “) to split that string into a bunch of individual words.  So, what happens when we transpose that to our CMD Prompt syntax?

PowerShell.exe –command “& {“this is a string”.split(“ “)}”

It errors out, as the CMD prompt strips out all of the quotes.  I tried every escape sequence I could think of and could not escape out those double quotes.  There is an easy workaround though – the single quote!  For simple string manipulation like this, you can probably get away with using single quotes instead of double quotes, like this:

PowerShell.exe –command “& {‘this is a string’.split(‘ ‘)}”

There is a potential downside to this: in PowerShell, single quotes mean a literal string.  In a PowerShell prompt, try this line of code:

Echo “I use PowerShell version $($PSVersionTable.psversion.major)!”

And you’ll get a nice phrase stating something like:

I use PowerShell version 4!

Now, try this one instead:

Echo ‘I use PowerShell version $($PSVersionTable.psversion.major)!’

You’ll notice that it doesn’t expand out the variables:

I use PowerShell version $($PSVersionTable.psversion.major)!

So, this workaround might solve the problem sometimes, but it’s not going to be the one true tool.  How do we solve this for real?  If you look at that PowerShell documentation again, you’ll notice that it also supports an argument called –encodedcommand and it even gives an example of how to make the encoded command.  If you want to use the documented encoding technique, make sure that you use single quotes for your command string, as that will make it much easier to embed quotes and other special characters into it.

I want to stress that an encoded command must be Unicode (16 bit) characters encoded into Base 64.  That means that things like the Notepad++ Base64 plugin aren’t going to help you, as you’re probably encoding 8 bit characters.  If you want to use a bigger text entry field, there are plenty of online Base 64 encoders that you can use, but you’ll have to make sure that you use one that supports a 16 bit character set (like UTF-16 or Unicode).  I’ve personally used this Base 64 encoder.

Once you have your Base 64 encoded string, you can invoke it by passing that string in quotes like this:

PowerShell.exe –encodedcommand “RQBjAGgAbwAgABwgSQAgAHUAcwBlACAAUABvAHcAZQByAFMAaABlAGwAbAAgAHYAZQByAHMAaQBvAG4AIAAkACgAJABQAFMAVgBlAHIAcwBpAG8AbgBUAGEAYgBsAGUALgBwAHMAdgBlAHIAcwBpAG8AbgAuAG0AYQBqAG8AcgApACEAHSA=”

So, what do we do with all of this in Orchestrator?  Well, once we’ve got our PowerShell arguments encoded so that the CMD prompt doesn’t pitch a fit when it receives them, we can go back to that “Run program in guest” workflow.  Once again, the program path should be:

 “C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe”

but this time, the arguments should be all the rest of that stuff:

–encodedcommand “RQBjAGgAbwAgABwgSQAgAHUAcwBlACAAUABvAHcAZQByAFMAaABlAGwAbAAgAHYAZQByAHMAaQBvAG4AIAAkACgAJABQAFMAVgBlAHIAcwBpAG8AbgBUAGEAYgBsAGUALgBwAHMAdgBlAHIAcwBpAG8AbgAuAG0AYQBqAG8AcgApACEAHSA”

It’s a bit circuitous, but it’s a reliable way to execute PowerShell cmdlets on your VMs through vRealize Orchestrator.

Comments

Popular posts from this blog

PowerShell Sorting by Multiple Columns

Clone a Standard vSwitch from one ESXi Host to Another

Deleting Orphaned (AKA Zombie) VMDK Files