I have found myself developing a small PowerShell script library to ease the burden of building and managing a large XenDesktop environment on Hyper-V. Today I want to provide a simple PowerShell script that can set the startup and shutdown actions for a pooled XenDesktop. I intend to provide more of these scripts through my blog as I find time to document them for public use and make them more user friendly.

When working with XenDesktop you always want to control startup through the Desktop Delivery Controller (DDC). The best way to prevent the SCVMM console from stepping all over the DDC is to disable the AutoStart for each VM. The last thing you want to happen is for SCVMM to startup VMs as soon as the server reboots, since those desktops are most likely in maintenance mode on the DDC. Therefore the script below sets the VM’s start action to “Never Auto Turn On VM.”

The default behavior of Hyper-V on shut down is to save the state of all VMs. When using a pooled desktop which relies on a “read-only” copy of a vDisk, saving state creates unnecessary work when the server shuts down. With pooled desktops, the write-cache consists of volatile data that is erased on bootup, so keeping the state provides no benefit. The most efficient, and completely safe approach is to just turn off the VM. Therefore, the script below sets the VM’s stop action to “Turn Off”

The script should be run from the SCVMM server that manages the XenDesktops that will have their startup and shutdown actions altered.

Usage: .\SetStartStop.ps1 VMMatchCriteria
Example: .\SetStartStop.ps1 “HVDesktop”

The example will locate all VMs with a name that matches HVDesktop (HVDesktop1, 23HVDesktop, etc.) and the query the current start and stop actions. If both actions are not set as expected, it will set the start and stop actions configured in the SCVMM database.

SetStartStop PowerShell Script
# Purpose:        Set Virtual Machine Start and Stop Actions <span class="code-keyword">for</span> XenDesktop
# Date Written:   14 April 2010
# Author:         Paul Wilson (no implied or expressed warranties)
# Usage:          setStartStop.ps1 [VM Name Match Criteria]

# Check to verify the name match criteria was supplied on the command-line

<span class="code-keyword">if</span> ($args -eq $<span class="code-keyword">null</span> -or $args.Count -lt 1)
{
  write-output <span class="code-quote">"Usage: SetStartStop.ps1 VMNameMatches"</span>
    write-output <span class="code-quote">"Example: .\SetStartStop.ps1 "</span><span class="code-quote">"HVDesktop"</span><span class="code-quote">" "</span>
  exit 1
}

# Store the name match criteria <span class="code-keyword">for</span> later use in finding the right VMs
$VMNameMatches = $args[0]

# Grab a handle to the local computer <span class="code-keyword">for</span> the VMM Server <span class="code-keyword">interface</span>
$VMMServer = Get-VMMServer -Computername <span class="code-quote">"localhost"</span>

# Get all the VMs that match the name criteria supplied
$VMs = Get-VM | where { $_.Name -match <span class="code-quote">"$VMNameMatches"</span> }
<span class="code-keyword">if</span> ($VMs -eq $<span class="code-keyword">null</span>)
{
  write-output <span class="code-quote">"No VMs match the pattern: $VMNameMatches"</span>
  exit 1
}
<span class="code-keyword">else</span>
{
    $LeftToGo = $VMs.Count
    <span class="code-keyword">if</span> ($LeftToGo -eq $<span class="code-keyword">null</span>)
    {
        $matchedString = <span class="code-quote">"Only one VM matched the pattern: {0}"</span> -f $VMNameMatches
        $LeftToGo = 1
    }
    <span class="code-keyword">else</span>
    {
     $matchedString = <span class="code-quote">"{0} VMs match the pattern: {1}"</span> -f $VMs.Count, $VMNameMatches
  }
    write-output $matchedString
}

# The loop below does the following <span class="code-keyword">for</span> each VM matched
# 1. First verifies the VM is not set as specified
# 2. Sets Start action to Never AutoStart the VM
# 3. Sets Stop action to Turn Off the VM when the host shuts down
# 4. Displays the number of VMs left to process

foreach ($VM in $VMS)
{
    $LeftToGo = $LeftToGo - 1
    <span class="code-keyword">if</span> ($VM.StartAction -eq <span class="code-quote">"NeverAutoTurnOnVM"</span> -and $VM.StopAction -eq <span class="code-quote">"TurnOffVm"</span>)
    {
        $ResultInfo = <span class="code-quote">"{0} is set correctly. {1} VMs left to go."</span> -f $VM.name, $LeftToGo
    }
    <span class="code-keyword">else</span>
    {
     Set-VM -VM $VM -StartAction NeverAutoTurnOnVM -StopAction TurnOffVM
       $ResultInfo = <span class="code-quote">"Actions set on {0}. {1} VMs left to go."</span> -f $VM.name, $LeftToGo
    }
    write-output $ResultInfo
}

If you found this information useful and would like to be notified of future blog posts, please follow me on Twitter @pwilson98 or visit my XenDesktop on Microsoft website.