Have you ever had machines not reboot properly? Have you had VMs you just don’t know if are awake and ready to serve your hungry customers? Have you ever just wanted to know if they are stepping through their paces? Well, here at XenApplePie, we have a solution for you! For only 35 payments of $0.00, you too can own this piece of automated automation!

But seriously. Sometimes you have a reboot policy set on your Delivery Group, and for some reason that pesky VM just doesn’t want to turn back on (From checking what it does, it looks like the DDC sends a shutdown and then a start command to reboot it). If you have had this happen, it can be frustrating to come in and either your hosting machine is off and users can’t access, or you can have a machine turned up to 11 to support your users. This little script, ran daily, can help prevent such frustrations and symptoms such as: pounding head on desk; shouting to the skies about your fury; verbal diarrhea of expletives not suitable for aural consumption.

Update below to the trim method used. The new method uses the split method versus the substring method. This method will work better as the length of the domain name won’t affect the outcome of the scripts and will save from making edits to the script for each domain. Another edit is for the HTML formatting to make it more readable in the report that is emailed.

So without further ado, well, ado ado ado. Here you go!

# This script was tested with 1912LTSRCU1 using Powershell 5.1.17763.1852 with PowerCLI version VMware PowerCLI 12.2.0 build 17538434 on vSphere 7.x.
# Build Date: 06292021
# https://www.pdq.com/blog/secure-password-with-powershell-encrypting-credentials-part-2/
# The above link contains the method to encrypting the password to use for the script and schedule in task scheduler.

# Loads Citrix snapins (This is assuming you have loaded the Citrix SDK / Studio on the machine that will run the check.)
Add-PSSnapin Citrix*

# vCenter connection section
# This tells PowerCLI to ignore invalid certicate action.
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -DisplayDeprecationWarnings $false -Scope Session -Confirm:$false

# This section is done via the method above in the pdq article for doing powershell scripts with encryption to show how to make the cred file, key file, and encrypt the information.
# The section also from https://notesofascripter.com
$password = Get-Content C:\scripts\creds.txt | ConvertTo-SecureString -Key (Get-Content C:\scripts\creds.key)
$credentials = New-Object System.Management.Automation.PsCredential("domain\username",$password)
Connect-VIServer somevcenteraddress -Credential $credentials
# End https://notesofascripter.com


# This is to get the list of machines from the delivery controller with the filter to get a specific set of machines.
$machines = Get-BrokerMachine -AdminAddress "delivery-controller.domainfqdn:80" -Filter {CatalogName -contains '*some_catalog_name_string*'}|Select-Object -Property machinename, desktopgroupname,inmaintenancemode

# This sets up an array to manipulate
$machine_array = @($machines)

# This goes through the array and removes VMs that have the "inmaintenancemode" value set as "True."
$machines_avail = $machine_array |where-object {$_.inmaintenancemode -ne "true"}

# The output of the Get-Brokermachine will retrieve the "machinename" with the domain preface. This trims the preface domain\servername. This method is better than the previously listed method as it will split at the "\" character, regardless of the length of the domain preface.
$vmtrim = $machine_avail.machinename
$vmtrimmed = (($vmtrim)|%{ ($_ -split '\\')[1]})

# This takes the result of the value above and assigns it to another variable that will be used to power on machines that have powered off.
$vmnames = $vmtrimmed

# This gets the additonal information from the "Get-VM" command and places it in a variable.
$vm = Get-VM $vmnames

# This creates and assigns the output of the "foreach if / else" loop. 
# This section was utilized from site "https://communities.vmware.com/t5/VMware-PowerCLI-Discussions/PowerCLI-start-multiple-VM-if-poweredOff/td-p/501598."
$output = $vm | foreach {

# This checks to see the value of the "PowerState" being "PoweredOff."
    if ($_.PowerState -eq "PoweredOff") {

# This shows a message that a VM was started and generates an output for your report.
        "Starting $($_.name) on $($_.VMHost)"

# This starts the VM and captures the output for the report.
        $StartingVMs = Start-VM $_ -Confirm:$false

    }

    else {

# This generates a message for the output for the report if the VM is already running.
        "$($_.name) is already running on $($_.VMHost)"

       

    }

}
# HTML Formatting
$style = "<style>BODY{font-family: Arial; font-size: 10pt;}"
$style = $style + "TABLE{border: 1px solid black; border-collapse: collapse;}"
$style = $style + "TH{border: 1px solid black; background: #dddddd; padding: 5px; }"
$style = $style + "TD{border: 1px solid black; padding: 5px; }"
$style = $style + "</style>"

# HTML Email Body
$body = $report | ConvertTo-Html -Head $style
# End of section from "https://communities.vmware.com/t5/VMware-PowerCLI-Discussions/PowerCLI-start-multiple-VM-if-poweredOff/td-p/501598."

# Generates email with attachment.
# This section to end was gotten from assistance from the author of https://notesofascripter.com. This also uses the .NET method of generating the email.
# Notesofascripter section
$date = Get-Date -Format "MM-dd-yyyy"
$emailFrom = "yourserviceemail@company.com"
$emailto = "youremailgroup@company.com"
$subject = "Daily Something Server Check| $date" 
$email = New-object System.Net.Mail.MailMessage 
$email.to.Add($emailto)
$emailCC = "emailgroup@company.com"
#$email.CC.Add($emailCC)
$Email.From = New-Object system.net.Mail.MailAddress $emailFrom
$email.Subject = $subject
$email.IsBodyHtml = $true
#$attachment = $Reports[1]
#$email.Attachments.add($attachment) If you want to do as attachment
$email.body = $body
 

$smtpserver="smtp.company.com" 
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($email)
;
# End of Notesofascripter section.

# Disconnect from vcenter
Disconnect-VIServer * -confirm:$false