You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell脚本无法将多驱动器卷信息写入CSV列的求助

问题修复与优化方案

核心问题分析

  1. 驱动器信息无法写入CSV:原脚本中$DriveSize | -list语法错误,且Get-Volume返回的多对象直接存入CSV会导致格式混乱,无法解析为规范列。
  2. 数据未汇总:每台服务器单独导出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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 07:40:25