PowerShell脚本无法将多驱动器卷信息写入CSV列的求助
问题修复与优化方案
核心问题分析
- 驱动器信息无法写入CSV:原脚本中
$DriveSize | -list语法错误,且Get-Volume返回的多对象直接存入CSV会导致格式混乱,无法解析为规范列。 - 数据未汇总:每台服务器单独导出CSV会覆盖之前的数据,无法实现批量汇总;原生PowerShell无直接导出Excel的命令,需借助专用模块实现。
修改后的完整脚本
# 导入所需模块 Import-Module ActiveDirectory # 若未安装ImportExcel模块,先执行:Install-Module -Name ImportExcel -Scope CurrentUser -Force Import-Module ImportExcel # 获取目标OU内的所有服务器 $servers = (Get-ADComputer -SearchBase "OU=OUGROUP" -Filter *).Name # 初始化数组存储所有服务器的采集结果 $allServerInfo = @() foreach ($server in $servers) { # 本地测试服务器连通性 $pingResult = Test-Connection -ComputerName $server -Count 1 -Quiet $status = if ($pingResult) { "Up" } else { "Down" } if (-not $pingResult) { # 服务器离线时记录基础信息 $serverInfo = [PSCustomObject]@{ ServerName = $server Status = $status BuildDate = $null CertificateValidFrom = $null CertificateValidTo = $null DriveInfo = $null TrellixLastUpdate = $null } $allServerInfo += $serverInfo continue } # 远程执行采集脚本 try { $remoteData = Invoke-Command -ComputerName $server -ScriptBlock { # 获取系统安装日期(用CIM替代老旧WMI) $os = Get-CimInstance -Class Win32_OperatingSystem $buildDate = $os.InstallDate # 获取证书信息(增加空值判断避免报错) $cert = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { -not $_.PSIsContainer } | Sort-Object NotBefore | Select-Object -First 1 $validFrom = if ($cert) { $cert.NotBefore } else { $null } $validTo = if ($cert) { $cert.NotAfter } else { $null } # 格式化驱动器信息(筛选有盘符的卷,计算关键指标) $driveInfo = Get-Volume | Where-Object { $_.DriveLetter } | ForEach-Object { $totalSize = if ($_.Size) { [math]::Round($_.Size / 1GB, 2) } else { 0 } $freeSpace = if ($_.SizeRemaining) { [math]::Round($_.SizeRemaining / 1GB, 2) } else { 0 } $usagePercent = if ($totalSize -gt 0) { [math]::Round(($totalSize - $freeSpace)/$totalSize * 100, 2) } else { 0 } # 整理为可读字符串,如需拆分多列可调整为结构化属性 "$($_.DriveLetter): 总大小=$totalSize GB, 可用=$freeSpace GB, 使用率=$usagePercent%" } -join "`n" # 获取Trellix更新时间(增加文件存在判断) $trellixPath = "C:\Program Files\Common Files\McAfee\Engine\AMCoreUpdater\amupdate.dat" $trellixDate = if (Test-Path $trellixPath) { [datetime](Get-ItemProperty $trellixPath).LastWriteTime.DateTime } else { $null } # 返回远程采集数据 [PSCustomObject]@{ BuildDate = $buildDate.DateTime CertificateValidFrom = $validFrom CertificateValidTo = $validTo DriveInfo = $driveInfo TrellixLastUpdate = $trellixDate } } -ErrorAction Stop # 合并本地与远程数据 $serverInfo = [PSCustomObject]@{ ServerName = $server Status = $status BuildDate = $remoteData.BuildDate CertificateValidFrom = $remoteData.CertificateValidFrom CertificateValidTo = $remoteData.CertificateValidTo DriveInfo = $remoteData.DriveInfo TrellixLastUpdate = $remoteData.TrellixLastUpdate } $allServerInfo += $serverInfo } catch { # 远程执行失败时记录错误信息 $serverInfo = [PSCustomObject]@{ ServerName = $server Status = "Error: $($_.Exception.Message)" BuildDate = $null CertificateValidFrom = $null CertificateValidTo = $null DriveInfo = $null TrellixLastUpdate = $null } $allServerInfo += $serverInfo } } # 导出汇总数据到CSV $csvPath = "C:\temp\ServerInfo_Summary.csv" $allServerInfo | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8 # 导出汇总数据到Excel(依赖ImportExcel模块) $excelPath = "C:\temp\ServerInfo_Summary.xlsx" $allServerInfo | Export-Excel -Path $excelPath -AutoSize -BoldTopRow Write-Host "汇总数据已导出到:`nCSV: $csvPath`nExcel: $excelPath"
关键修改点说明
- 连通性测试本地化:避免在远程服务器ping自身的无效操作,确保状态判断准确。
- 驱动器信息格式化:筛选有效盘符卷,计算总大小、可用空间、使用率,整理为可读字符串存入CSV;如需拆分多列,可修改为动态生成
DriveC_TotalSize等属性。 - 异常处理强化:服务器离线、远程执行失败、文件/证书不存在时均会记录对应状态,避免脚本中断。
- 数据汇总逻辑:所有服务器数据存入本地数组后统一导出,避免文件覆盖;使用
ImportExcel模块实现Excel导出,支持自动列宽、表头加粗等格式优化。 - 命令现代化:用
Get-CimInstance替代Get-WmiObject,提升兼容性与性能。
使用注意事项
- 执行脚本需具备AD读取权限、远程服务器的WMI/CIM访问权限。
- 若未安装
ImportExcel模块,需以管理员身份运行PowerShell并执行Install-Module -Name ImportExcel -Scope CurrentUser -Force。 - 可根据需求调整
DriveInfo的格式,如需拆分多列,可修改远程脚本块中驱动器信息的处理逻辑,生成包含各驱动器属性的哈希表后动态添加到PSCustomObject。
内容的提问来源于stack exchange,提问作者BobSnarley
相关产品推荐
相关产品推荐

