Tutorial: Leveraging PowerShell and PowerCLI
PowerShell and PowerCLI provide a number of valuable activities, but knowledge of PowerShell is necessary to take advantage of these activities. This tutorial introduces techniques to leverage some of PowerShell and PowerCLI’s features without delving too deeply into PowerShell.
This example will query the list of powered on virtual machines running on an ESX Host. The results will be cached between runs of the workflow. The workflow will be executed using the PowerWF Agent, and will send an email whenever virtual machines have been powered on or powered off. If no virtual machines have changed state, the workflow will not send an email.
Topics Discussed
- Drag and drop of PowerCLI activities
- Drag and drop of PowerShell activities
- Disabling activities.
- Caching data between runs
- Conditional processing
- Using the PowerWF Agent
Procedure
- Create a new workflow project called “vmPowerStateMonitor”
- The pipeline is one of the most basic concepts in PowerShell. A pipeline is essentially a way to join multiple PowerShell commands together, where the output of one command is used as an input to the next command. Since this is a fairly complicated example, it is safe to assume that a pipeline will be useful if not completely necessary. From the VMware PowerCLI activity pack, drag “PipelineSequence” to the canvas.

In PowerWF it is possible for a pipeline to have one or many activities so if there is no harm in adding a Pipeline whenever using PowerShell within PowerWF. - Since the “PipelineSequence” was selected from within the VMware PowerCLI activities, PowerWF automatically created a “ConnectVIServer” activity to connect to the virtual center or ESX host. Set the server, user, and password for the virtual center or ESX host.

- Since the purpose of this tutorial was to display virtual machines, the obvious next step is to get a list of virtual machines. A quick glance at the PowerCLI activity pack shows an activity called GetVM. Drag this onto the canvas into the pipeline.

- At this point it is worth doing a quick test to see what data the GetVM activity returns. Drop a DataGrid activity outside the pipeline. This way PowerWF will connect the output of the pipeline to the input of the DataGrid, regardless of what other activities are added inside the pipeline.

- Running this workflow will generate a data grid that provides information that is useful for the rest of the tutorial. Specifically the PowerState and Name columns will be of interest.

- PowerShell v2.0 has a selectObject command that can be used to select the specific fields that are needed; in this case Name and PowerState. Drop this activity in the pipeline and set the “Property” value to “Name, PowerState”.

There are countless examples of selectObject for PowerShell available online. A quick search will reveal both simple and complex examples that can be included in PowerWF. - The goal of the tutorial was to filter the list down to only include machines with a PowerState of “PoweredOn”. Scanning through the list of available PowerShell activities reveals “WhereObject”. The mouse-over text states that it will create a filter that controls which objects will be passed along the pipeline. Drop this activity below the “selectObject1” in the pipeline.

- The WhereObject requires a “Filter” to be set. Searching online for “where-object powershell” shows that the filter should be in the form of:
{$_.Color -eq “orange”}
“$_” in PowerShell is short-hand to reference a property in the current pipeline, so “$_.Color” grabs the color of the current object.
“-eq” is a comparator, in this case checking that two things are equal. The whole expression is wrapped in “{}”.
With that in mind, the where expression to be used for this example is:
- Running the workflow now returns a data grid with a list of virtual machines that are currently powered on. In retrospect, perhaps the select object was a little aggressive in only selecting the virtual machine name and the power state. This is not a problem since PowerWF lets an activity be temporarily disabled. Right-click on “selectObject1” and click “Disable” from the popup menu.

- Running the workflow now returns a data grid with all of the available columns but only displaying virtual machines that are powered on. Add the NumCPU and MemoryMB columns to the “selectObject1” activity.

- Re-enable the “selectObject1” activity using the popup menu that was used to disable it. Running the workflow now provides the data of interest in a reasonable format.

- Now that the correct data is selected, it is time to move on to the more interesting part of the tutorial; displaying only virtual machines that have changed in power state. This is accomplished by caching the results each time the workflow executes and reporting on the differences. Type “cache” in the toolbox search bar and then drag “CacheData” above the “DataGridView” activity.

- At this point, the “DataGridView” and “CacheData1” are both bound to the output of the pipeline. The desired behavior is to have “DataGridView” bound to the output of “CacheData1”. Since no properties have changed on “DataGridView”, the easiest way to correct the binding would be to delete the activity and re-add it, letting PowerWF correct the binding.
To directly set the binding, select “DataGridView” and click
for the Input. Switch the binding from the output of the “pipelineSequence1” to “CacheData1” and click OK.
- The first time this workflow is executed, the data grid will look very similar to previous runs. The most notable change is that it is now a tabbed view, showing items that have been added and removed from the cache.

Note: Since this is the first run, the “Removed” tab will not contain any data. - Run the workflow again. Unless someone happened to power on or off a virtual machine between runs, the “Added” and “Removed” tabs will both be empty. This is close to the goal, but ideally nothing would appear if no machines had been powered on or off. This can be accomplished by placing the output inside a conditional activity, such as the “IfElse” activity in the “Windows Workflow v3.0” activity pack. Drop this activity above the data grid activity.

- Drag the “DataGridView” in the workflow from its current position to within the “ifElseBranchActivity1” activity.

- It is now necessary to set the condition for the “ifElseBranchActivity”. In this example a “Declarative Rule Condition” will be used.

- A declarative rule condition requires a condition name and an expression. The name can be anything meaningful, such as “powerstateChange”. The expression is a little trickier. The expression to see if the cache has changed is:
((CacheData)this.GetActivityByName(“cacheData1”)).HasChanged”
The expression warrants some explanation:
“(CacheData)” tells PowerWF that the object returned by “this.GetActivityByName” is a CacheData object. This is the same as type-casting in languages such as c# or Java.
“GetActivityByName” is straight-forward; it is looking for an activity named “cacheData1”.
Since “GetActivityByName” was type-cast to a “CacheData” object, it is possible to access its “HasChanged” property which happens to be a Boolean value. The expression could also be written as:
((CacheData)this.GetActivityByName(“cacheData1”)).HasChanged” == true - Run the workflow again. Unless someone powered on or off a virtual machine, nothing should be displayed. If possible power on or off a virtual machine then rerun the workflow. Only this virtual machine should appear in the data grid; on “Added” if it was powered on, or on “Removed” if it was powered off.

Notice that the power state on the removed tab is being incorrectly displayed as 1. This is because the “Removed” tab is based on data that is cached. - Delete the “DataGridView” activity and drop in the “toHTML” activity in its place. Set the “Input” to the output of the “CacheData1” activity.

- Click “Select Columns” and select all columns except for “PowerState”.

- Drop the “SendMailBySMTP” activity below the “toHTML1” activity in the “ifElseBranchActivity1”. Configure the properties for the mail server that will be used, as discussed in the previous tutorial. Specifically, Username, Password, To, From, Subject, and the mail server Host and Port will need to be set. EnableSSL is server dependent. The body should be bound to the HTML table output and BodyHTML should be set to true.

- Power on or off a virtual machine, and then run the workflow. An email should be sent to the target email address. Running the workflow again should not send another email.

- The workflow now checks for virtual machine power state changes and notifies a user via email. The only thing missing is deploying the workflow to the agent so that it runs at a set interval. On the “Deploy” tab, click the “Agent” button on the ribbon bar.

- Configure the workflow to run every hour on the Local host.

The PowerWF Agent will now run the workflow every hour and email a report of any virtual machines that have been powered on or off during that time period. If no machines have changed state, no email will be sent.
Summary
This tutorial showed how to drag-and-drop PowerShell and PowerCLI activities into a PowerWF workflow rather than entering scripts in the PowerShell console. Strategies were discussed for learning basic PowerShell syntax to leverage the PowerShell and PowerCLI activities.
The tutorial discussed caching data between runs, conditional processing, and deployment to the PowerWF Agent. Automatic and manual binding of activities was briefly discussed. Disabling instructions for debugging purposes was also touched upon.
2 years ago - link

