PowerShell脚本动态获取GPO XML属性值报错问题求助
解决PowerShell动态获取GPO属性值并存储到PSObject的问题
你的代码主要问题出在动态属性名的获取和批量处理环节:
- 使用
Out-String会将属性名转为带换行符的字符串,导致Select-Object -ExpandProperty无法识别有效属性名——单独调用时可能刚好是单个属性,所以能运行,但循环中多属性场景就报错 - 当对象有多个属性时,
($_|Get-Member -MemberType property | Select-Object Name).Name返回的是数组,直接赋值给$Name后遍历逻辑错误 - 没有将获取到的属性值添加到创建的
PSObject中,不符合“存储到PSObject”的需求 - 未处理
$obj是单个对象而非数组的情况(部分GPO的Extension可能只有一个节点)
修改后的完整代码
# Generate GPO Report $GPOReport = Get-GPO -All | ForEach-Object { [xml](Get-GPOReport -Guid $_.Id -ReportType Xml) } # Blank Array to store PSObject $arr = @() # Loop through each of the reports foreach($GPOR in $GPOReport){ $PSObject = New-Object -TypeName psobject # Add Policy Meta Data to PSObject $PSObject | Add-Member -MemberType NoteProperty -Name "PolicyName" -Value $GPOR.GPO.Name $PSObject | Add-Member -MemberType NoteProperty -Name "CreatedDate" -Value ($GPOR.GPO.CreatedTime -split 'T')[0] $PSObject | Add-Member -MemberType NoteProperty -Name "ModifiedDate" -Value ($GPOR.GPO.ModifiedTime -split 'T')[0] # Process Computer Policy Settings if($ComputerPolicy = $GPOR.GPO.Computer.ExtensionData.Extension){ $objNodes = $ComputerPolicy | Select-Xml -XPath * | Select-Object -ExpandProperty Node # Handle both single node and array of nodes $nodesToProcess = if($objNodes -is [array]) { $objNodes } else { @($objNodes) } foreach($node in $nodesToProcess){ # Get all property names of the node $propertyNames = $node | Get-Member -MemberType Property | Select-Object -ExpandProperty Name foreach($propName in $propertyNames){ $propValue = $node.$propName # Add property to PSObject, prefix with Computer_ to avoid conflicts with user policy $PSObject | Add-Member -MemberType NoteProperty -Name "Computer_$propName" -Value $propValue -Force } } } # Process User Policy Settings if($UserPolicy = $GPOR.GPO.User.ExtensionData.Extension){ $objNodes = $UserPolicy | Select-Xml -XPath * | Select-Object -ExpandProperty Node $nodesToProcess = if($objNodes -is [array]) { $objNodes } else { @($objNodes) } foreach($node in $nodesToProcess){ $propertyNames = $node | Get-Member -MemberType Property | Select-Object -ExpandProperty Name foreach($propName in $propertyNames){ $propValue = $node.$propName # Add property to PSObject, prefix with User_ to avoid conflicts $PSObject | Add-Member -MemberType NoteProperty -Name "User_$propName" -Value $propValue -Force } } } # Add the populated PSObject to the array $arr += $PSObject } # Output the result $arr
关键修改说明
- 元数据直接绑定:用
Add-Member将GPO名称、创建/修改日期直接作为NoteProperty添加到PSObject,完成基础信息存储 - 统一节点处理逻辑:通过判断节点类型,将单个节点转为数组处理,避免重复写分支代码
- 正确获取属性名:直接提取纯属性名字符串数组,去掉
Out-String导致的格式污染 - 动态属性注入:遍历每个属性名,通过
$node.$propName直接取值,用前缀区分计算机/用户策略属性,避免重名冲突 - 强制属性覆盖:添加
-Force参数,确保不同GPO的同名属性能正常写入,保证PSObject结构一致性
内容的提问来源于stack exchange,提问作者EMC
相关产品推荐
相关产品推荐

