PowerCLI variable behavior strange

An attempt was made to collect several properties of virtual machines, but for some reason all output records only contain information about the last virtual machine

$CSV

basically contains a couple of virtual machine names:

VMName
Centos1
Centos2

      

Here is the code I'm using:

$VMdata = @()
$line = '' | Select VMName, VMToolStatus, VMToolVersion, UUID, Tag, Notes

foreach($entry in $csv){
    $line.VMName = $entry.VMname
    $line.VMToolStatus = (get-vm $entry.VMname).ExtensionData.Guest.ToolsRunningStatus
    $line.VMToolVersion = (get-vm $entry.VMname).ExtensionData.Guest.ToolsVersion
    $line.UUID = (get-vm $entry.VMname).ExtensionData.Config.UUID
    $line.Notes = (get-vm $entry.VMname).Notes
    $line.Tag = get-vm $entry.VMname | Get-TagAssignment | Select -ExpandProperty Tag  | select Name
    $VMdata += $line
}

$VMdata | Export-Csv -Path c:\report.csv -NoTypeInformation -Force

      

here is the CSV output - as you can see both lines contain information about VM Centos2.

"VMName","VMToolStatus","VMToolVersion","UUID","Tag","Notes","StartupOrder"

"CentOS2","guestToolsRunning","2147483647","564d7fd7-e58f-e546-ecdf-c347e35cd453",,"Test Note",

"CentOS2","guestToolsRunning","2147483647","564d7fd7-e58f-e546-ecdf-c347e35cd453",,"Test Note",

      

When I debug it, I see that after the first loop, the $line

correct VM Centos1 information is updated and then added to $VMData

.

However, when the second loop starts, for example after execution, line.VMName = $entry.VMname

I see both variables $line

and $VMData

are updated with the name CentOS2.

So my question is, why is it $VMData

updated along with $line

?

I've used this piece of code before and it worked great.

I am running the following PS version

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      14393  1480 

      

VMware PowerCLI 6.5 Release 1 build 4624819

+3


source to share


1 answer


You can fix this by moving the part $line = ''

inside the loop ForEach

:

$VMdata = @()

foreach($entry in $csv){
    $line = '' | Select VMName, VMToolStatus, VMToolVersion, UUID, Tag, Notes
    $line.VMName = $entry.VMname
    $line.VMToolStatus = (get-vm $entry.VMname).ExtensionData.Guest.ToolsRunningStatus
    $line.VMToolVersion = (get-vm $entry.VMname).ExtensionData.Guest.ToolsVersion
    $line.UUID = (get-vm $entry.VMname).ExtensionData.Config.UUID
    $line.Notes = (get-vm $entry.VMname).Notes
    $line.Tag = get-vm $entry.VMname | Get-TagAssignment | Select -ExpandProperty Tag  | select Name
    $VMdata += $line
}

$VMdata | Export-Csv -Path c:\report.csv -NoTypeInformation -Force

      

I believe the problem occurs because in this case the PowerShell variable acts as a pointer (reference type), so when updated a $line

second time, it actually affects the existing result in $vmdata

.

By moving $line = ''

around inside the loop, you reset the variable on each iteration so that it doesn't fire that way.



I really recommend that you do this instead:

$CSV | ForEach-Object {
    $Props = @{
        VMName = $_.VMname
        VMToolStatus = (get-vm $_.VMname).ExtensionData.Guest.ToolsRunningStatus
        VMToolVersion = (get-vm $_.VMname).ExtensionData.Guest.ToolsVersion
        UUID = (get-vm $_.VMname).ExtensionData.Config.UUID
        Notes = (get-vm $_.VMname).Notes
        Tag = (get-vm $_.VMname | Get-TagAssignment | Select -ExpandProperty Tag  | select Name)
    }
    New-Object -TypeName PSObject -Property $Props
} | Export-Csv -Path c:\report.csv -NoTypeInformation -Force

      

This uses a hash table to create a PowerShell object in a ForEach-Object loop, which you can then pipe the output to Export-CSV directly.

+4


source







All Articles