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
相关产品推荐
相关产品推荐

