PowerCLI变量的奇怪行为

3

尝试收集虚拟机的几个属性,但由于某些原因,输出中的所有条目都只包含有关最后一个虚拟机的信息。

$CSV 基本上包含了几个虚拟机名称:

VMName
Centos1
Centos2

这是我正在使用的代码:

$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

这里是CSV输出 - 正如您所看到的,两行都包含了有关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",

当我进行调试时,我可以看到在第一个循环后,$line已经更新为VM Centos1的正确信息,然后将其添加到$VMData中。

然而,当第二个循环开始时,例如执行line.VMName = $entry.VMname后,我发现两个变量$line$VMdata都被更新为CentOS2名称。

所以,我的问题是为什么$VMdata会随着$line一起更新?
我之前使用过这段代码,它运行得很好。
我正在运行以下版本的PS。
Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      14393  1480 

VMware PowerCLI 6.5 Release 1版本编号为4624819。

1个回答

4

您可以通过将$line = ''部分移动到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

我认为问题出现的原因是在这种情况下,PowerShell变量就像指针(引用类型)一样运作,因此当您第二次更新$line时,它实际上影响了$vmdata中现有结果。
通过将$line = ''移动到循环内部,您可以在每次迭代中重置变量,从而避免这种情况。
但我实际上建议您使用以下方法:
$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

这使用哈希表在ForEach-Object循环内创建一个PowerShell对象,然后您可以直接将输出导入Export-CSV。


1
FYI,我刚刚添加了第二个解决方案,从代码角度来看更加简洁。 - Mark Wragg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接