I did some further tests, and it looks like the script was not capturing all types of power off events.
I also added sort on VM name and Hard Disk name.
functionGet-VMInfo{ param(
[string]$Name
)
$vm=Get-View-ViewType VirtualMachine -Property Name, runtime.powerState, Guest.net, Config.Hardware.numCPU, Config.Hardware.MemoryMB, Runtime.Host, Guest.GuestFullName,
Config.GuestFullName, Parent, ResourcePool, Config.Hardware.Device, Config.version, guest.toolsversionstatus,
Config.Files.VMPathName -filter @{'Name'="^$Name$"}
if($vm){
$t=Get-View$vm.ResourcePool-Property Name, Parent
while($t.getType().Name -eq"ResourcePool"){
$t=Get-View$t.Parent-Property Name, Parent
}
if($t.GetType().Name -eq"ClusterComputeResource"){
$cluster=$t.Name
}else{
$cluster="Stand Alone Host"
}
while($t.getType().Name -ne"Datacenter"){
$t=Get-View$t.Parent-Property Name, Parent
}
$datacenter=$t.Name
$vm.Config.Hardware.Device|Where-Object{$_.GetType().Name -eq"VirtualDisk"}|
Select-Object@{N="vCenter";E={$script:vmhost=Get-View-Id $vm.Runtime.Host;$script:vmhost.Client.ServiceUrl.Split('/')[2]}},
@{N="VM";E={$vm.Name}},
@{N='powerState';E={$vm.runtime.powerState}},
@{N='IP';E={[string]::Join(',',($vm.Guest.Net|ForEach-Object{$_.IpAddress|Where-Object{$_.Split('.').Count -eq4}|ForEach-Object{$_}}))}},
@{N='NumCPU';E={$vm.config.Hardware.NumCpu}},
@{N='Memory GB';E={$vm.Config.Hardware.MemoryMB|ForEach-Object{[math]::Round($_/1kb,2)}}},
@{N='VMHost';E={$script:esx=Get-View-Id $vm.Runtime.Host;$script:esx.name}},
@{N='GuestOS';E={$vm.Guest.GuestFullName}},
@{N='ConfiguredOS';E={$vm.Config.GuestFullName}},
#@{N="Folder";E={$path}},
@{N="Cluster";E={$cluster}},
@{N="Datacenter";E={$datacenter}},
@{N="Scsi";E={$_.UnitNumber}},
@{N="Hard Disk";E={$_.DeviceInfo.Label}},
@{N="Disk datastore";E={$_.Backing.Filename.Split(']')[0].TrimStart('[')}},
@{N="Disk capacity GB";E={$_.CapacityInKB|ForEach-Object{[math]::Round($_/1MB,2)}}},
@{N="Disk type";E={
if($_.Backing.GetType().Name -match"flat"){
"Flat"
}else{
$_.Backing.CompatibilityMode
}}
},
@{N='DeviceName';E={
if($_.Backing.GetType().Name -match'raw'){
($_.Backing.DeviceName)-join'|'
}else{
$script:lunnaa=(Get-View-Id $_.Backing.Datastore).Info.Vmfs.Extent[0].DiskName
$script:lun=$script:esx.Config.StorageDevice.ScsiLun|Where-Object{$_.CanonicalName-eq$script:lunnaa}
$script:lun.Descriptor|Where-Object{$_.Id-match'vml.'}|Select-Object-ExpandProperty Id
}}
},
@{N='LUN NAA';E={
if($_.Backing.GetType().Name -match'raw'){
$lunUuid=$_.Backing.LunUuid
$script:lun=$script:esx.Config.StorageDevice.ScsiLun|Where-Object{$_.Uuid-eq$lunUuid}
$script:lun.CanonicalName
}else{
$script:lunnaa
}}
},
@{N='LUN ID';E={
$dev=$script:esx.Config.StorageDevice.PlugStoreTopology.Device|Where-Object{$_.Lun-eq$script:lun.Key}
$script:esx.Config.StorageDevice.PlugStoreTopology.Path|Where-Object{$_.Device-eq$dev.Key}|
Select-Object-First 1-ExpandProperty LunNumber
}
},
@{N='VMConfigFile';E={$VM.config.files.VMpathname}},
@{N='VMDKPath';E={$_.Backing.FileName}},
@{N="HW Version";E={$vm.Config.version}},
@{N="Tools Status";E={$vm.guest.toolsversionstatus}},
@{N="NIC Name";E={($vm.config.hardware.device|Where-Object{($_.DeviceInfo.Label-like"Network*")}).DeviceInfo.Label -join'|'}},
@{N="Mac";E={($vm.Config.Hardware.Device|Where-Object{$_.DeviceInfo.Label-like"Network*"}).MacAddress -join'|'}},
@{N="Portgroup";E={
$nic=$vm.Config.Hardware.Device|Where-Object{$_.DeviceInfo.Label-like"Network*"}
[string]::Join(',',(
$nic|ForEach-Object{
if($_.DeviceInfo.Summary-notmatch'DVSwitch'){
$_.DeviceInfo.Summary
}else{
Get-View-ViewType DistributedVirtualPortgroup -Property Name -Filter @{'Key'=$_.Backing.Port.PortgroupKey}|
Select-Object-ExpandProperty Name
}}))}
}
}
}
$fileName='.\VMreport.csv'
$configFile=$fileName.Replace('.csv','.cfg')
$eventTypes='VmReconfiguredEvent','VmRemovedEvent','VmDeployedEvent','VmCreatedEvent','VmPoweredOffEvent',
'VmPoweredOnEvent','DrsVmPoweredOnEvent'
$start=(Get-Date).AddDays(-1)
$hash=@{}
$now=Get-Date
if(Test-Path-Path $fileName){
Import-Csv-Path .\VMreport.csv -UseCulture |
ForEach-Object-Process {
$hash.Add("$($_.VM)$($_.'Hard Disk')",$_)
}
$start=[DateTime](Get-Content-Path $configFile)
Get-VIEvent-Start $start-MaxSamples ([int]::MaxValue)|
Where-Object{$eventTypes-contains($_.GetType()).FullName.Split('.')[2]-or$eventTypes-contains($_.GetType()).BaseType.Name }|
Group-Object-Property {$_.VM.Name}|
ForEach-Object-Process {
Write-Host"Looking at $($_.Name)"
$_.Group|Sort-Object-Property CreatedTime |
ForEach-Object-Process {
$event=$_
switch($event.GetType().FullName.Split('.')[2]){
'VmRemovedEvent'{
$rows=$hash.GetEnumerator()|Where-Object{$_.Key-match"^$($event.VM.Name)"}
$rows|ForEach-Object-Process {
$hash.Remove("$($_.Value.VM)$($_.Value.'Hard Disk')")
}
}
{'VmDeployedEvent','VmCreatedEvent'-contains$_}{
Get-VMInfo-Name $event.VM.Name|
ForEach-Object-Process {
$hash.Add("$($_.VM)$($_.'Hard Disk')",$_)
}
}
'VmReconfiguredEvent'{
Get-VMInfo-Name $event.VM.Name|
ForEach-Object-Process {
$hash.Item("$($_.VM)$($_.'Hard Disk')")=$_
}
}
{'VmPoweredOnEvent','DrsVmPoweredOnEvent'-contains$_}{
$rows=$hash.GetEnumerator()|Where-Object{$_.Key-match"^$($event.VM.Name)"}
$rows|ForEach-Object-Process {
$_.Value.PowerState='poweredOn'
$hash.Item($_.Key)=$_.Value
}
}
'VmPoweredOffEvent'{
$rows=$hash.GetEnumerator()|Where-Object{$_.Key-match"^$($event.VM.Name)"}
$rows|ForEach-Object-Process {
$_.Value.PowerState='poweredOff'
$hash.Item($_.Key)=$_.Value
}
}
}
}
}
}else{
Get-View-ViewType Virtualmachine -Property Name -Filter @{'Config.Template'='False'}|
ForEach-Object-Process {
Write-Host"Looking at $($_.Name)"
Get-VMInfo-Name $_.Name|
ForEach-Object-Process {
$hash.Add("$($_.VM)$($_.'Hard Disk')",$_)
}
}
}
$hash.Values|
Sort-Object-Property VM,'Hard Disk'|
Export-Csv-Path $fileName-NoTypeInformation -UseCulture
$now.ToString()|Out-File-FilePath $configFile