VMware Cloud Community
DZ1
Hot Shot
Hot Shot
Jump to solution

I should really have this by now, but...

I am trying to write a simple script to write out some data.  I normally don't use Export-Csv, but I am for this report.  I went back and read about how Export-Csv may output data like [System.Object] and [System.String], depending on how Powershell sees the data.  For the IPaddres section, I was getting them, and then I made the adjustment for it to output the write way, but for the hard drive data, I can't get it to work.

Since some VMs have multiple drives, I see that Powershell shows it has a FlatHardDiskImpl, but I don't know how to get it to output correctly into the csv file.  I have tried many things for the hard drive section: subexpression, Select-Object, Array @(), but I can't get export-csv to show both drives.  I really thought I would get this by now, but there is still so much more to learn.  Here is the script.

$AllReport = @()
Get-vm | Foreach {
$VMS = $_
$Report =  "" | Select VMName, IPaddress, FQDN, OStype, 'Memory(GB)', CPU, 'HD(GB)'
$Report.VMname = $vms.name
$Report.IPaddress = $vms.guest | Foreach { write $_.IPaddress }
$Report.FQDN = $VMS.guest.HostName
$Report.OStype = $VMS.Guest.OSFullname
$Report.'Memory(GB)' = $VMS.MemoryMB / 1024
$Report.CPU = $VMS.NumCPU
$Report.'HD(GB)' = $VMS.HardDisks | Select CapacityKB | Foreach { write ($_.CapacityKB / 1MB) } #I can't get this to work correctly
#Write $Report
$Allreport += $Report
}
$AllReport | Export-Csv -NoTypeInformation C:\file.csv
ii C:\File.csv
0 Kudos
1 Solution

Accepted Solutions
mattboren
Expert
Expert
Jump to solution

Hello, DZ1-

If you are looking to get a list of disk sizes in the 'HD(GB)' property of the $Report object, you can change the line that you mention that you cannot get to work correctly to something like:

...
$Report.'HD(GB)' = ($VMS.HardDisks | %{[Math]::Round($_.CapacityKB/1MB,1)}) -join ","
...

That should get you the given VM's hard disk size(s) in that property.

And, later, you talk about the New-Object cmdlet.  Here is an example of using this cmdlet in your script:

&{Get-VM | Foreach {
   
$vm = $_
   
New-Object -TypeName PSObject -Property @{
        VMname
= $vm.name
        IPs
= ($vm.guest | %{$_.IPaddress}) -join ","
        FQDN
= $vm.guest.HostName
        OStype
= $vm.Guest.OSFullname
       
"Memory(GB)" = $vm.MemoryMB / 1KB
        CPU
= $vm.NumCPU
       
"HDs(GB)" = ($vm | Get-HardDisk | %{[Math]::Round($_.CapacityKB/1MB,1)}) -join ","
    }
## end new-object
}} | Export-Csv -NoTypeInformation -UseCulture C:\file.csv
ii C:\file.csv

By using New-Object, you do not need to store things, you do not need to add them to an array, so you can help keep memory usage down in your scripts (not that you will run your client machine out of memory, but you can cause scripts to fail with System.OutOfMemoryException errors).  And, you can see how it is a bit cleaner with less repetitive typing.  I also used the Get-HardDisk cmdlet here, as the .HardDisks property is obsolete.

How do these examples do for you?

View solution in original post

0 Kudos
4 Replies
mrksiddiqui
Enthusiast
Enthusiast
Jump to solution

Does this helps

Connect-VIServer MYVISERVER
$MyCollection = @()
$AllVMs = Get-View -ViewType VirtualMachine | Where {-not $_.Config.Template}
$SortedVMs = $AllVMs | Select *, @{N="NumDisks";E={@($_.Guest.Disk.Length)}} | Sort-Object -Descending NumDisks
ForEach ($VM in $SortedVMs){
$Details = New-object PSObject
$Details | Add-Member -Name Name -Value $VM.name -Membertype NoteProperty
$DiskNum = 0
Foreach ($disk in $VM.Guest.Disk){
$Details | Add-Member -Name "Disk$($DiskNum)path" -MemberType NoteProperty -Value $Disk.DiskPath
$Details | Add-Member -Name "Disk$($DiskNum)Capacity(MB)" -MemberType NoteProperty -Value ([math]::Round($disk.Capacity/ 1MB))
$Details | Add-Member -Name "Disk$($DiskNum)FreeSpace(MB)" -MemberType NoteProperty -Value ([math]::Round($disk.FreeSpace / 1MB))
$DiskNum++
}
$MyCollection += $Details
}
$MyCollection | Out-GridView
# Export-Csv, ConvertTo-Html or ConvertTo-Xml can be used above instead of Out-Gridview

Here is the author of the script

http://www.virtu-al.net/2010/01/27/powercli-virtual-machine-disk-usage/

If this helps answer your question please consider awarding points!
DZ1
Hot Shot
Hot Shot
Jump to solution

Thanks, the information you sent isn't quite what I need, but it did give me an idea.  I tried to incorporate this into my script:

$Report.'HD(GB)' = $VMS | Foreach { ($_ | Get-HardDisk) | Foreach { $HD = New-Object PSObject; $HD | Add-Member -MemberType NoteProperty -Name Drive -Value $_.CapacityKB } }

I'm hoping that I am on the right track here, I have not used the New-Object cmdlet much, but it is something that I know I need to learn more about. 

0 Kudos
mattboren
Expert
Expert
Jump to solution

Hello, DZ1-

If you are looking to get a list of disk sizes in the 'HD(GB)' property of the $Report object, you can change the line that you mention that you cannot get to work correctly to something like:

...
$Report.'HD(GB)' = ($VMS.HardDisks | %{[Math]::Round($_.CapacityKB/1MB,1)}) -join ","
...

That should get you the given VM's hard disk size(s) in that property.

And, later, you talk about the New-Object cmdlet.  Here is an example of using this cmdlet in your script:

&{Get-VM | Foreach {
   
$vm = $_
   
New-Object -TypeName PSObject -Property @{
        VMname
= $vm.name
        IPs
= ($vm.guest | %{$_.IPaddress}) -join ","
        FQDN
= $vm.guest.HostName
        OStype
= $vm.Guest.OSFullname
       
"Memory(GB)" = $vm.MemoryMB / 1KB
        CPU
= $vm.NumCPU
       
"HDs(GB)" = ($vm | Get-HardDisk | %{[Math]::Round($_.CapacityKB/1MB,1)}) -join ","
    }
## end new-object
}} | Export-Csv -NoTypeInformation -UseCulture C:\file.csv
ii C:\file.csv

By using New-Object, you do not need to store things, you do not need to add them to an array, so you can help keep memory usage down in your scripts (not that you will run your client machine out of memory, but you can cause scripts to fail with System.OutOfMemoryException errors).  And, you can see how it is a bit cleaner with less repetitive typing.  I also used the Get-HardDisk cmdlet here, as the .HardDisks property is obsolete.

How do these examples do for you?

0 Kudos
DZ1
Hot Shot
Hot Shot
Jump to solution

Thank you so much, I used ' $Report.'HD(GB)' = ($VMS.HardDisks | % {[Math]::Round($_.CapacityKB/1MB,1) }) -join "," ' and it worked perfectly.  Just when I think I'm doing great, a problem occurs and I get stuck, I was on a Powershell roll, and then someone asked me for Excel output, and I quickly knew I still doin't know Jack about Powershell.  I'm glad it happened though, the experience will make me go back and learn more. 

Thanks again for your help, I really appreciate it. 

0 Kudos