Category Archives: Powershell

Track VM Changes

With large VMware implementations and large teams to support those environments, it becomes difficult to track of all your team is following the company standards while changing any existing virtual machine or creating new ones. Following is a sample script on how you can track it automatically via emails. The parameters being tracked can be changed as per your individual environment standards. We will implement this on the Datacenter level with the vCenter, however, you can change the target as per your requirement.

Prerequisite: Sending SMTP mails from your vCenter server should be configured.

First, identify the scenario which could indicate a machine configuration change or new machine creation, e.g. a VM is created, VM is configured or VM is powered off.

Now create a new alarm on the datacenter level within vCenter with following Events:



Create a folder under C:\Windows\ or any other preferred location and copy the following three scripts in it.

  1. Batch File:

Create a batch file createalert.bat with following content:

@echo off
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "C:\windows\folder\createalert.ps1 %1"
  1. Powershell Script:

Create a powershell script createalert.ps1 with following content:

param ([string] $srv = $null)
"C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1"
if (-not (Get-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) {
Add-PSSnapin VMware.VimAutomation.Core} 
$VC1 = ""
$date = Get-Date -DisplayHint DateTime -Format "yyyy-M-d" 
Connect-VIServer -Server $VC1 -WarningAction SilentlyContinue
Get-VM $srv |Select Name,PowerState, vmhost, memoryGB, numcpu, notes, folder, resourcepool, version, 
@{N="Guest OS";E={ ($_ | Get-vmguest).osfullName}},
@{N="Cluster";E={ ($_ | Get-Cluster).Name}}, 
@{N="Network Name";E={ foreach($nic in $_ | Get-networkadapter){$}}},
@{N="Network Type";E={ foreach($nic in $_ | Get-networkadapter){$nic.type}}},
@{N="IP Address";E={ ($_ | Get-vmguest).ipaddress}},
@{N="Datastore Name";E={ ($_ | Get-Datastore).Name}},
@{N="DS Size GB";E={ ($_ | Get-Datastore).CapacityGB}},
@{N="DS Free Space GB";E={ ($_ | Get-Datastore).FreespaceGB}},
@{N="Total Disk GB"; E={  ($_ | Get-harddisk | measure-object -prorerty CapacityGB -sum).Sum}}, 
@{N="Hard Disks";E={ foreach($disk in $_ | Get-harddisk){$}}},
@{N="Disk Size GB";E={ foreach($disk in $_ | Get-harddisk){$disk.capacityGB}}},
@{N="Disk Format";E={ foreach($disk in $_ | Get-harddisk){$disk.storageformat}}},
@{N="Disk File Name";E={ foreach($disk in $_ | Get-harddisk){$disk.filename}}}|out-file c:\windows\folder\report\Report-$srv-$Date.txt -encoding ASCII
Disconnect-VIServer -server $VC1 -Force -Confirm:$false
cscript c:\windows\folder\sendmail.vbs "c:\windows\folder\report\Report-$srv-$Date.txt"
remove-item "c:\windows\folder\report\Report-$srv-$Date.txt"
  1. VBScript:

Create a vbscript sendmail.vbs with following content. You can also write the code below in powershell itself:

Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile (WScript.Arguments(0), ForReading)
Set objMessage = CreateObject("CDO.Message") 
objMessage.Subject = "VM State Alert"
objMessage.From = "" 
objMessage.To = ""
objMessage.TextBody = "State of following VM has been changed. Please verify VM configuration:" & vbCRLF
objMessage.TextBody = objMessage.TextBody & objTextFile.ReadAll()
objMessage.Configuration.Fields.Item ("") = 2 
objMessage.Configuration.Fields.Item ("") = ""
objMessage.Configuration.Fields.Item ("") = 25

Once all the three scripts are in place, reopen the alarm created earlier and add the following action:


Under configuration, mention the path of your batch file:

c:\windows\folder\createalert.bat %VMWARE_ALARM_EVENT_VM%

VMWARE_ALARM_EVENT_VM is a parameter which would pass the hostname of affected VM into the batch file.

Once this alert is configured and enabled, you will get an email every time a new VM is created or an existing VM is modified, and you can keep track of your organizational VM policies.


Decoding Powershell Help

Once you have found what command would serve your purpose (read here), you certainly need to understand its syntex and parameters. Help is one place where you can go and understand this, however, you need to know how to decode the help in powershell.

help commandlet or get-help commandlet


Here you see three different syntex in which this command can be run. All three can be used based on the input parameter values you have in hand.

Run help with -Full parameter to see more details for each parameter e.g. help get-service -FullCapture.JPG

You will notice there are different set of parenthesis around different variables. These can be read as follows:

  1. [] around parameter e.g. [-Name] signifies its positional i.e. you don’t need to type -Name to signify that you are specifying a name. You can simply type the value at its mentioned position e.g. 1 in this case.
  2. It entire parameter along with its value type is enclosed in [] then that parameter is optional. e.g. -DisplayName is required paramter whereas -ComputerName is not.

You can find more valuable input under the NOTES section in help specially the aliases that can be used for any particular command along with some examples.

Search Powershell Commands

With more and more technologies starting to use Powershell for its operations, sometimes it becomes difficult to find command for a particular task. Now when you launch Powershell, some of the modules are by default loaded into the memory based on operating system being used but some of them are not loaded by default although they are available on the computer. The good thing is, if you run a command from a module not loaded, it will get auto loaded. In order to see what modules are loaded, run the following command:


To see what modules are available which can be loaded run:

get-module -List

You can manually import a module using:

import-module -Name Nameofmodule

Now lets decode a commandlet. The ‘Get’ in get-module is the verb part of it and ‘Module’ is the noun. With so many modules for various applications and numerous commands within each module, to find any particular command can be challenging specially if you don’t have the manual in front of you. Here is how you can do it easily using get-command:

get-command -verb get -noun *

This command with fetch all commands starting with get-


You can use only verb, only noun or both.