Sean Killeen bio photo

Sean Killeen

Just a guy trying to get better at writing bios.

Email Twitter Facebook Google+ LinkedIn Instagram Github Stackoverflow Foursquare
Edit this page | Issue? Question?

Problem

I need to create a scheduled task that runs a powershell script that takes actions against my VMWare environment.

For this article, we’ll use the example of shutting down all VMs in a Non-Production folder when we’re not scheduled to be at our desk (a real problem I’d faced).

Solution

Before you Begin

This solution assumes that you’ve already got PowerCLI configured and know your way around a little bit of PowerCLI/PowerShell.

Step 1: Create a VMWare Credential Store in a File

Firstly, your script will need login permissions to connect to a VI server. We can set this up ahead of time by creating an encrypted credential store for your server.

  • Open PowerCLI as an Administrator.
  • Run the following command:
New-VICredentialStoreItem -host 'yourhost.yourdomain.com' -user 'yourusername' -password 'yourpassword' -file C:\Path\To\Store\TheFile\In.creds

NOTES: When creating the credential store, you’ll want to create it as the same user that will eventually need to access it. If you create the credential file as user X but run the Scheduled Task as user Y, your task will be unable to read the file. Also, you don’t need to have a file extension, but I use “creds” just to make it clearer to me. Obviously, replace the host, username, password, and path with something that makes sense to you.

Step 2: Create a Script that Uses the Credential Store

Create a PowerShell Script Similar to the following:

#Stop an error from occurring when a transcript is already stopped
$ErrorActionPreference="SilentlyContinue"
Stop-Transcript | out-null
 
#Reset the error level before starting the transcript
$ErrorActionPreference="Continue"
Start-Transcript -path C:\temp\Shutdown_NonProductionVMs.log -append
 
#Add the VMWare Snap-in
Add-PSSnapin -Name VMWare.VimAutomation.Core
 
#Get the Credentials
$creds = Get-VICredentialStoreItem -file  C:\temp\pscreds.creds
 
#Connect to the server using the credentials file
Connect-VIServer -Server $creds.host -User $creds.User -Password $creds.Password
 
#Get all VMs within the non-production VMs folder and then shut them down
#NOTE the -WhatIf tag, which will stop it from shutting down the VMs until we're sure the script is good.
 
Get-Folder -Name "03. Non-Production VMs" | Get-VM | Shutdown-VMGuest -WhatIf
 
#Clean Up
Disconnect-VIServer -Force -Confirm:$false
Remove-PSSnapin -Name VMWare.VimAutomation.Core
Stop-Transcript

Step 3: Set up the Scheduled Task

  • Create a scheduled task in the task scheduler.
  • Run the task with the highest privileges.
  • In the action for the task, run the program/script powershell.exe.
  • For the arguments, use "c:\Path\To\YourScript.ps1" (with quotes in case of spaces – good habit).

Test your task manually several times. Make sure the log output looks right.

Taking it Live: Removing the -WhatIf

When the task is scheduled and you’re satisfied it will run as you intended it, edit the script to remove the -WhatIf line. This means the Guest OSes will actually be shut down.

Afterwards: Gotchas

I gained some insights from this process, mostly by trial and error. I thought I should share the fruits of my errors with you:

  • Do not run a powershell script directly as a scheduled task. It does not work. Use the powershell.exe "C:\Path\To\script.ps1" format to execute.

References