PowerShell技术求助:如何用if/elseif语句为CSV添加显卡相关列?
问题分析与修正方案
核心错误点
- 语法错误:在创建
[PsCustomObject]的哈希表内部直接嵌入if/elseif语句,PowerShell不允许在哈希表定义中使用流程控制逻辑,这是导致报错的直接原因。 - Job重复读取:多次调用
Receive-Job $videocontroller,第一次读取后Job的输出就会被清空,后续的$nvidiavideocontroller_output和$AMDvideocontroller_output会获取不到数据。 - Wait-Job参数遗漏:
Wait-Job中未包含$bioscontroller2,可能导致该Job未完成就接收输出,获取到空值。 - 显卡判断逻辑错误:使用
-ilike "*Intel*"判断$intelvideocontroller_output对象,应该直接判断对象是否存在($null -ne $intelvideocontroller_output),因为之前已经通过过滤得到了对应显卡的对象。 - 显卡兼容性问题:原脚本用
elseif会导致一台机器如果同时有Intel核显+NVIDIA独显的情况,只会记录其中一个,不符合需求。
修正后的完整脚本
# 用户需要创建包含主机名的txt文件 function ReadHostnames($initialDirectory) { [void] [System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog if ($initialDirectory) { $OpenFileDialog.initialDirectory = $initialDirectory } $OpenFileDialog.filter = '所有文件 (*.*)|*.*' [void] $OpenFileDialog.ShowDialog() return $OpenFileDialog.FileName } $FilePermissions = ReadHostnames C:\ $FilePermissions = Get-Content $FilePermissions Write-Host "正在收集信息,请稍候..." $counter = 0 foreach ($computername in $FilePermissions) { Write-Host "正在处理 $computername ($counter/$($FilePermissions.Count))" if (Test-Connection -BufferSize 32 -Count 1 -ComputerName $computername -Quiet) { # 启动所有异步Job $computersystemJob = Get-WmiObject Win32_ComputerSystem -ComputerName $computername -AsJob $videocontrollerJob = Get-WmiObject win32_videocontroller -ComputerName $computername -AsJob $biosJob = Get-WmiObject win32_bios -ComputerName $computername -AsJob $computerSystemModelJob = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $computername -AsJob $userlogon = Get-CimInstance -ClassName Win32_ComputerSystem -Property UserName -ComputerName $computername # 等待所有Job完成,超时10秒 Wait-Job -Job $computersystemJob, $videocontrollerJob, $biosJob, $computerSystemModelJob -Timeout 10 | Out-Null # 接收Job输出,只读取一次videocontrollerJob的结果 $computersystemOutput = Receive-Job $computersystemJob $allVideoControllers = Receive-Job $videocontrollerJob $biosOutput = Receive-Job $biosJob $computerSystemModelOutput = Receive-Job $computerSystemModelJob # 过滤各品牌显卡 $intelVideo = $allVideoControllers | Where-Object { $_.Name -ilike "*Intel*" } $nvidiaVideo = $allVideoControllers | Where-Object { $_.Name -ilike "*NVIDIA*" } $amdVideo = $allVideoControllers | Where-Object { $_.Name -ilike "*AMD*" } # 先初始化所有可能的列,确保CSV结构一致 $newrow = [PSCustomObject]@{ Host_name = $computersystemOutput.Name Model_Name = $computerSystemModelOutput.Model Serial_Number = $biosOutput.SerialNumber BIOS_Version = $biosOutput.SMBIOSBIOSVersion Last_User_Logon = $userlogon.UserName Intel_Card = $null IntelGraphics_Version = $null Nvidia_Card = $null NvidiaGraphics_Version = $null AMD_Card = $null AMDGraphics_Version = $null } # 分别判断各品牌显卡是否存在,填充对应字段(支持多显卡共存) if ($null -ne $intelVideo) { $newrow.Intel_Card = $intelVideo.Name -join "; " # 多显卡用分号分隔 $newrow.IntelGraphics_Version = $intelVideo.DriverVersion -join "; " } if ($null -ne $nvidiaVideo) { $newrow.Nvidia_Card = $nvidiaVideo.Name -join "; " $newrow.NvidiaGraphics_Version = $nvidiaVideo.DriverVersion -join "; " } if ($null -ne $amdVideo) { $newrow.AMD_Card = $amdVideo.Name -join "; " $newrow.AMDGraphics_Version = $amdVideo.DriverVersion -join "; " } $newrow | Export-Csv -Path C:\HostnameData.csv -Append -NoTypeInformation # 清理所有Job Remove-Job -Job $computersystemJob, $videocontrollerJob, $biosJob, $computerSystemModelJob -Force $counter++ } else { Write-Host "远程计算机 $computername 处于离线状态" } }
关键优化说明
- 修正语法错误:将流程控制逻辑移到
[PsCustomObject]创建之后,通过直接修改对象属性的方式填充显卡信息,避免在哈希表内使用if/else。 - Job一次性读取:只读取一次
$videocontrollerJob的输出,再从中过滤各品牌显卡,避免多次读取导致数据丢失。 - 统一CSV列结构:初始化所有可能的显卡列(即使为空),确保导出的CSV文件列数一致,不会因为不同机器的显卡情况导致列错乱。
- 支持多显卡共存:去掉
elseif改用独立的if判断,同时处理同一台机器上的多个不同品牌显卡,多显卡时用分号分隔名称和版本。 - 修复Wait-Job参数:添加
$computerSystemModelJob到等待列表,确保所有Job完成后再接收输出。
内容的提问来源于stack exchange,提问作者gameandscripts
相关产品推荐
相关产品推荐

