A. Mikkelsen

VMware ESX scripts, commands, tools and other nice to know things that will make your virtualization days easier!!!!

If you ever have experienced that after your vCenter server reboots – due to Windows updates, the “VMware VirtualCenter Server” service is not starting?

I have seen it a few times and every time it’s during a weekend 🙁

So to make sure your vCenter service (or other) is always running you could use this powershell script to check if a service is running, and if not start it.
To make sure you know if the service wasn’t started after a reboot or other cause, I have added a mail function to the script 🙂

function FuncCheckService{
    $arrService = Get-Service -Name $ServiceName
    if ($arrService.Status -ne "Running"){
        Start-Service $ServiceName
        FuncMail -To "to-email@domain.com" -From "from-mail@domain.com"  -Subject "Servername : ($ServiceName) service started." -Body "Service $ServiceName started" -smtpServer "relay.mailserver.com"

function FuncMail {
    #param($strTo, $strFrom, $strSubject, $strBody, $smtpServer)
    param($To, $From, $Subject, $Body, $smtpServer)
    $msg = new-object Net.Mail.MailMessage
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    $msg.From = $From
    $msg.Subject = $Subject
    $msg.IsBodyHtml = 1
    $msg.Body = $Body

FuncCheckService -ServiceName "VMware VirtualCenter Server"

Create a PS1 file and schedule it to run every 15 or 30 minutes.

It works great and is simple….

If you want to configure a hosts NTP server list through PowerCLI you have a few cmdlet at your disposal.

  • Get-VMHostNtpServer
  • Remove-VMHostNtpServer
  • Add-VMHostNtpServer
  • Get-VMHostService
  • Set-VMHostService
  • Get-VmhostFirewallException
  • Restart-VMHostService

Get a list of NTP servers on a host.

Get-VMHostNtpServer -VMHost "esx01.lab.local"

To remove a specific NTP server from a host NTP server list.

Remove-VMHostNtpServer -VMHost "esx01.lab.local" -NtpServer '' -Confirm:$false

To remove all NTP servers on a hosts NTP server list.

$arrNTPList = Get-VMHostNtpServer -VMHost "esx01.lab.local"
Remove-VMHostNtpServer -VMHost "esx01.lab.local" -NtpServer $arrNTPList -Confirm:$false

To add a single NTP server to a hosts NTP server list.

Add-VMHostNtpServer -VMHost "esx01.lab.local" -NtpServer "dk.pool.ntp.org" -Confirm:$false

To add a a list of NTP servers to a hosts NTP server list.

$arrNTPServers = ("dk.pool.ntp.org","de.pool.ntp.org","us.pool.ntp.org")
Add-VMHostNtpServer -VMHost "esx01.lab.local" -NtpServer $arrNTPServers -Confirm:$false

To set the NTP deamon (service) to start automatic.

Set-VMHostService -HostService (Get-VMHostservice -VMHost (Get-VMHost "esx01.lab.local") | Where-Object {$_.key -eq "ntpd"}) -Policy "Automatic"

Open firewall to allow the NTP deamon to communicate with the NTP server.

Get-VmhostFirewallException -VMHost "esx01.lab.local" -Name "NTP Client" | Set-VMHostFirewallException -enabled:$true

To restart the NTP deamon (service) after you have configured it – without restarting the host.

$ntpd = Get-VMHostService -VMHost "esx01.lab.local" | where {$_.Key -eq 'ntpd'}
Restart-VMHostService $ntpd -Confirm:$false

Since Vizioncore came out with vRanger 4.x, last year, I been working on porting the VBS script “vRanger Script version 2.0” to Powershell.
During this time I have found several bugs/missing functionality in the vAPI.
Vizioncore have corrected the bugs with new releases of vRanger.
The first vRanger version where all vAPI cmdlets worked in was version 4.2.3.

Porting the script from VBS presented me with a few challenges.

  • A reported error in the Get-Date cmdlet in Powershel 2.0.
    Had to use a workaround.

A few words on the scrips functionality.

  • Control vRanger backups from vCenter (simple – one interface).
  • Perform a FULL backup of DiskO of a VM.
  • Perform a FULL backup of all disks of a VM.
  • Backup a VM on a specific weekday.
  • Control what week (Even/Odd).
  • Create a log file.
  • Delete previous backup files from repository.
  • Delete previous savepoints.
  • Send an email when the jobs are completed – incl. succes/errors.
  • Offload the files to tape – TSM
  • Send mail when TSM is finished offloading backup files.
  • And many more…..

When I started coding the script, I found, that if I used functions for all functionality the script was easier to read. Using functions also supplied me with the opportunity of reusing functions – less work :-).

Some of the functions was created using examples posted and mailed by Scott Harold from Quest and TheVesi./vEcoShell.


The script can be downloaded here.

A quick overview of the functions.
Include the right PSSnapins

function LoadSnapin{
    Add-PSSnapin vRanger.API.PowerShell -ErrorAction SilentlyContinue
    Add-PSSnapin vmware.VimAutomation.core -ErrorAction SilentlyContinue


Delete all previous savepoints – from the repository.

function RemoveAllSavePoints{
	param ($RASP_RepoName)
	$RASP_repoID = Get-Repository | where {$_.Name -eq $RASP_RepoName}
	$RASP_SPlist = Get-RepositorySavePoint -ID $RASP_repoID.Id

	foreach ($RASP_SP in $RASP_SPlist){
		#write $RASP_SP
		Remove-SavePoint -SavePointsToRemove $RASP_SP

RemoveAllSavePoints "Remote-Location"

Is a backup job exist with the same name as the one to create – delete it.

function Del-vRangerBackupJobs {
	param ($delJobName)
	$delTemplateID = Get-JobTemplate | where {$_.JobName -eq $delJobName}
	# Verify that a BackupJob named XXX is present before deleting it.
	if ($delTemplateID){
		#write $delTemplateID.JobName
		Remove-JobTemplate -id $delTemplateID.Id

Del-vRangerBackupJobs "$Wednesday-Even"

Create the list of VMs to exclude.

function Filter-VMbyCF {
    param ($customF, $val)
    foreach ($vm in $vmlist) {
        $vm.CustomFields | ForEach-Object {
            $cf = $_
            if ($_.Key -like $customF -and $_.Value -like $val){
                    return $vm.name

function New-vRangerExcludeList {
    param ($exclude, $include)
    $excludeArray = @()
    $exclude | ForEach-Object {
        if ($include -notcontains $_.Name){
            $excludeArray += ($_.Config.Uuid)
    return $excludeArray

$vmlist = Get-VM
$tmplist = Get-Template
$vmlist= $vmlist + $tmplist
$vmFilter = Filter-VMbyCF $customField $CFValue
$vmlistview = $vmlist | Get-View
$excludeList = New-vRangerExcludeList -exclude $vmlistview -include $vmFilter

Create the new backup job.

function New-vRangerBackupJob {
	param ($customJobName, $customCFValue, $customFieldName, $customRepoName, $customExcludeList, $customEmail)
        $jobDesc = "This backup job is created by Logica for use in DR.  All VMs with a Custom Field labeled: $customFieldName with a value of: $customCFValue will be backed up"
        $jobEntity = Get-InventoryEntity -Type VirtualCenter
	$jobRepos = Get-Repository | where {$_.Name -eq $customRepoName}
        $jobFlag = New-BackupFlag -CheckDestinationFreeSpace:$true -UseCompression:$true -PerformNetworkBackupOnFailure:$true

	# Check if all disks or just disk 0
	if ($customJobName -like "*-All*"){
		#write "All - Disks"
		#Add-BackupJobTemplate -JobName $customJobName -JobDescription $jobDesc -JobEntity $jobEntity -ExcludedVMList $customExcludeList -NotificationList $email -TargetRepository $jobRepos -Flags $jobFlag -NumberOfSavePoints 1 -SpaceSavingTechnologyTypeFlag None
		Add-BackupJobTemplate -JobName $customJobName -JobDescription $jobDesc -JobEntity $jobEntity -ExcludedVMList $customExcludeList -NotificationList $customEmail -TargetRepository $jobRepos -Flags $jobFlag -NumberOfSavePoints 1 -SpaceSavingTechnologyTypeFlag None -SpaceSavingCountThreshold 6 -SpaceSavingPercentSizeThreshold 50
		#write "Only Disk 0"
		#Add-BackupJobTemplate -JobName $customJobName -JobDescription $jobDesc -JobEntity $jobEntity -ExcludedVMList $customExcludeList -NotificationList $email -IncludedDiskList 0 -TargetRepository $jobRepos -Flags $jobFlag -NumberOfSavePoints 1 -SpaceSavingTechnologyTypeFlag None
		Add-BackupJobTemplate -JobName $customJobName -JobDescription $jobDesc -JobEntity $jobEntity -ExcludedVMList $customExcludeList -NotificationList $customEmail -IncludedDiskList 0 -TargetRepository $jobRepos -Flags $jobFlag -NumberOfSavePoints 1 -SpaceSavingTechnologyTypeFlag None -SpaceSavingCountThreshold 6 -SpaceSavingPercentSizeThreshold 50

New-vRangerBackupJob "Wednesday-Even" "Wednesday-Even" "Backup" "Remote-Location" $excludeList "to@email.com"

Start the backup job.

function Run-BackupJob{
	param ($runJobName)
	$runTemplateID = Get-TemplateID $runJobName
	Run-JobsNow $runTemplateID

Run-BackupJob "Wednesday-Even"

Wait for the backup job to finish.

function Get-TemplateID{
	$arrTemplate = get-jobtemplate | where {$_.JobName -eq $tmpJobName}
	return $arrTemplate.ID

function WaitForJobToFinish{
	param ($strWaitJob)
	$strCompleted = "NotStarted"
        Start-Sleep -Seconds 300	# 5 minutes
	$jobTemplates = get-JobTemplate | where {$_.JobName -eq $strWaitJob}
	foreach ($job in $jobTemplates){
			$tasksinfo = get-job |where {$_.ParentJobTemplateID -eq $job.TemplateVersionID}
			foreach ($task in $tasksinfo){
				Start-Sleep -Seconds 300	# 5 minutes
				$strCompleted = $task.JobState

                # Make sure job is running - if not start it...
                if ($task.JobState -eq $NULL -or $task.JobState -eq "NotStarted"){
                    Run-BackupJob $strWaitJob
                    Start-Sleep -Seconds 120	# 2 minutes
		while ($strCompleted -notmatch "Completed")

WaitForJobToFinish "Wednesday-Even"

Send TSM finished mail.

function FuncMail {
	#param($strTo, $strFrom, $strSubject, $strBody, $smtpServer)
	param($To, $From, $Subject, $Body, $smtpServer)

	$msg = new-object Net.Mail.MailMessage
	$smtp = new-object Net.Mail.SmtpClient($smtpServer)
	$msg.From = $From
	$msg.Subject = $Subject
	$msg.IsBodyHtml = 1
	$msg.Body = $Body

FuncMail -To "to@email.com" -From "from@email.com" -Subject "vRanger Pro: TSM backup finished" -Body "Your Body" -smtpServer "your.mailserver.com"

A friend on the Danish VMUG pointed me towards this simple backup script, from GestaltIT.com.

The script creates a snapshot of a VM (from a CSV file) and creates a Thin Provisioned clone based on the snapshot, on a specified datastore (from the CSV file).

This a smart and simple way to create a backup of a list of VM’s.

It’s a must read for PowerCLI users.

VMware has released their hardening guide for vSphere 4.0.

There is more than 100 guidelines to choose from, divided between

  • Introduction
  • Virtual Machines
  • Host (both ESXi and ESX)
  • vNetwork
  • vCenter
  • Console OS (for ESX only)


A must have


For all us VMware fan boys/girls this toolbar is a must…

Download it from vmwaresupport.toolbar.fm

Time keeping in a virtual environment can be a challenge to setup.

To help you, VMware has maintained a KB on the subject.

The KB presents best practices for achieving accurate timekeeping in Windows Guest operating systems. These recommendations include a suggested configuration for timesynchronization in the guest and on the host.

A more specific guide also exists for Windows and Linux servers:
For Windows read:
For Linux read:

It’s great reading, but very nerdy 🙂

A few weeks ago I came across a podcast on http://get-scripting.blogspot.com about Powershell.

I highly recommend that all people using powershell check it out.

Get the latest and the archived podcasts at

New layout


Today I had to change the theme because the old theme, wasn’t compatible with the latest version of WordPress.org.

I hope you like it, I’ll try to personalize it during the next couple of weeks :-).

Today I needed to create a list of all users connected to a vCenter sever through the Client.
And during so I created a few variants 🙂

This creates a list of all usernames connected to the vCenter server through a vCenter Client.

$svcRef = new-object VMware.Vim.ManagedObjectReference
$svcRef.Type = "ServiceInstance"
$svcRef.Value = "ServiceInstance"
$serviceInstance = get-view $svcRef
$sessMgr = get-view $serviceInstance.Content.sessionManager
foreach ($sess in $sessMgr.SessionList){
   write "$($sess.UserName)"

If you want to see a witch clients have been idle for 60 minutes try this.

$svcRef = new-object VMware.Vim.ManagedObjectReference
$svcRef.Type = "ServiceInstance"
$svcRef.Value = "ServiceInstance"
$serviceInstance = get-view $svcRef
$sessMgr = get-view $serviceInstance.Content.sessionManager
foreach ($sess in $sessMgr.SessionList){
    if (($sess.LastActiveTime).addminutes(60) -lt (Get-Date)){
        write "$($sess.UserName)"

If you the want to terminate the sessions that have been inactive  for more than 60 minute

$svcRef = new-object VMware.Vim.ManagedObjectReference
$svcRef.Type = "ServiceInstance"
$svcRef.Value = "ServiceInstance"
$serviceInstance = get-view $svcRef
$sessMgr = get-view $serviceInstance.Content.sessionManager
$oldSessions = @()
foreach ($sess in $sessMgr.SessionList){
    if (($sess.LastActiveTime).addminutes(60) -lt (Get-Date)){
        $oldSessions += $sess.Key

You can modify the hell out of this script to suit your needs and be my guest….

You can download the full script here.

The scripts are based on code found  at the PowerCLI community by LucD.