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

PowerShell导出SCCM数据至CSV含嵌套JSON如何修复并扁平化?

问题原因

Invoke-CMWmiQuery 返回的查询结果中,每个字段是对应WMI类的嵌套属性对象,并非直接的字符串、数值类标量值。直接将结果管道传给Export-CSV时,cmdlet无法自动解析嵌套属性的实际取值,会直接将嵌套对象序列化为类JSON结构的字符串写入单元格,就会出现你截图里的效果。
另外你原WQL语句中重复查询了两次SMS_G_System_MBAM_POLICY.MBAMPolicyEnforced字段,直接导出会生成重名列,需要先删除重复查询项。

修复方案

不需要复杂处理,只需要在导出前提取嵌套属性的实际值、展平对象结构即可,两种写法效果完全一致,按需选择:

方案1:Select-Object计算属性(写法更简洁)

Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1" @initParams
# 站点配置
$SiteCode = Get-PSDrive -PSProvider CMSITE
$ProviderMachineName = "machine_name" # SMS Provider机器名
Set-Location "$($SiteCode.Name):\"

$WQL = @"
select SMS_R_System.NetbiosName, 
SMS_R_System.LastLogonUserName, 
SMS_R_System.OperatingSystemNameandVersion, 
SMS_G_System_BITLOCKER_DETAILS.DriveLetter, 
SMS_G_System_MBAM_POLICY.MBAMPolicyEnforced, 
SMS_G_System_BITLOCKER_DETAILS.EncryptionMethod
from SMS_R_System 
inner join SMS_G_System_MBAM_POLICY on SMS_G_System_MBAM_POLICY.ResourceID = SMS_R_System.ResourceId 
inner join SMS_G_System_BITLOCKER_DETAILS on SMS_G_System_BITLOCKER_DETAILS.ResourceID = SMS_R_System.ResourceId 
where (SMS_G_System_BITLOCKER_DETAILS.DriveLetter = "C:" or SMS_G_System_BITLOCKER_DETAILS.DriveLetter = "D:")
"@
$collectionID = 'CDT003DO'

Invoke-CMWmiQuery -Query $WQL | Select-Object `
    @{Name='设备名'; Expression={$_.SMS_R_System.NetbiosName}},
    @{Name='最后登录用户名'; Expression={$_.SMS_R_System.LastLogonUserName}},
    @{Name='系统版本'; Expression={$_.SMS_R_System.OperatingSystemNameandVersion}},
    @{Name='BitLocker盘符'; Expression={$_.SMS_G_System_BITLOCKER_DETAILS.DriveLetter}},
    @{Name='MBAM策略生效状态'; Expression={$_.SMS_G_System_MBAM_POLICY.MBAMPolicyEnforced}},
    @{Name='加密方式'; Expression={$_.SMS_G_System_BITLOCKER_DETAILS.EncryptionMethod}} |
    Export-Csv -Path "C:\Test\output1.csv" -NoTypeInformation -Encoding UTF8

方案2:遍历结果生成PSCustomObject(逻辑更直观)

# 前面导入模块、配置站点、定义WQL的代码和方案1完全一致
Invoke-CMWmiQuery -Query $WQL | ForEach-Object {
    [PSCustomObject]@{
        设备名 = $_.SMS_R_System.NetbiosName
        最后登录用户名 = $_.SMS_R_System.LastLogonUserName
        系统版本 = $_.SMS_R_System.OperatingSystemNameandVersion
        BitLocker盘符 = $_.SMS_G_System_BITLOCKER_DETAILS.DriveLetter
        MBAM策略生效状态 = $_.SMS_G_System_MBAM_POLICY.MBAMPolicyEnforced
        加密方式 = $_.SMS_G_System_BITLOCKER_DETAILS.EncryptionMethod
    }
} | Export-Csv -Path "C:\Test\output1.csv" -NoTypeInformation -Encoding UTF8

两种方案导出后所有字段都会以纯文本形式平铺在单行单元格中,不会再出现嵌套结构。

优化建议(适配每日计划任务自动导出)
  • 增加集合筛选提升查询效率:你原代码定义了$collectionID但未在WQL中使用,全量查询所有设备速度慢。在WQL的where条件前增加集合关联即可指定查询集合内的设备:
    inner join SMS_FullCollectionMembership on SMS_FullCollectionMembership.ResourceID = SMS_R_System.ResourceId
    where SMS_FullCollectionMembership.CollectionID = 'CDT003DO'
    and (SMS_G_System_BITLOCKER_DETAILS.DriveLetter = "C:" or SMS_G_System_BITLOCKER_DETAILS.DriveLetter = "D:")
    
  • 导出文件名增加日期后缀,避免每日运行覆盖历史报告:将导出路径改为"C:\Test\BitLocker状态报告_$(Get-Date -Format 'yyyyMMdd').csv"即可。
  • 计划任务配置要点:
    • 运行账户选择拥有SCCM WMI查询权限、本地导出目录读写权限的域账户
    • 启动程序配置为powershell.exe,添加参数-ExecutionPolicy Bypass -File "你的PS脚本存储路径.ps1",绕过默认执行策略拦截
    • 导出目录不要选择C盘根目录、Program Files等受UAC管控的路径,避免权限不足导致导出失败
    • 可在脚本开头增加日志记录逻辑,方便排查每日运行失败的问题

当前异常导出效果参考

内容的提问来源于stack exchange,提问作者user18704773

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:15:37