Powershell 变量的奇怪行为

Powershell 变量的奇怪行为,powershell,powercli,Powershell,Powercli,尝试收集一些VM的属性,但由于某些原因,输出中的所有条目仅包含关于最后一个VM的信息 $CSV基本上包含两个VM名称: VMName Centos1 Centos2 以下是我正在使用的代码: $VMdata = @() $line = '' | Select VMName, VMToolStatus, VMToolVersion, UUID, Tag, Notes foreach($entry in $csv){ $line.VMName = $entry.VMname $l

尝试收集一些VM的属性,但由于某些原因,输出中的所有条目仅包含关于最后一个VM的信息

$CSV
基本上包含两个VM名称:

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 name更新

所以,我的问题是为什么
$VMdata
会随着
$line
一起更新

我以前使用过这段代码,它工作得很好

我正在运行以下版本的PS

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

VMware PowerCLI 6.5第1版build 4624819

您可以通过将
$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对象循环中创建PowerShell对象,然后通过管道将输出直接导出CSV。

FYI刚刚添加了第二个解决方案,从代码角度看,该解决方案更简洁。