PowerShell 4.0中如何筛选获取所有本地组内的本地用户
获取本地组中的本地用户:PowerShell解决方案及Ansible集成
我明白你现在的困境——Win32_GroupUser本身没有LocalAccount属性,没法直接加Filter,而你之前尝试的循环匹配又因为WMI路径格式和变量展开错误没得到结果。下面给你几个可行的方案,同时解释之前代码的问题所在。
问题分析:你之前的代码为什么没返回结果?
你的循环逻辑里有三个关键问题:
- 变量在单引号中无法展开:
'Win32_Group.Name="$group"'里的$group被单引号包裹,PowerShell不会把它替换成实际的组名,应该用双引号或者字符串拼接。 - 匹配逻辑错误:
GroupComponent和PartComponent是完整的WMI路径(比如\\SERVER\root\cimv2:Win32_Group.Name="Administrators",SID="S-1-5-32-544"),不是只包含Name字段的简单字符串,直接匹配Win32_Group.Name="$group"根本找不到对应条目。 - 效率极低:嵌套循环会重复调用
Get-CimInstance -ClassName Win32_GroupUser无数次,对系统资源是不必要的消耗。
解决方案1:用WQL关联查询(推荐,高效)
直接通过WQL语句关联Win32_GroupUser、Win32_Group和Win32_UserAccount,一次性筛选出本地组和本地用户的关联关系:
# 获取关联关系并提取易读的组名和用户名 Get-CimInstance -Query @" SELECT GroupComponent, PartComponent FROM Win32_GroupUser WHERE GroupComponent IN (SELECT __PATH FROM Win32_Group WHERE LocalAccount='True') AND PartComponent IN (SELECT __PATH FROM Win32_UserAccount WHERE LocalAccount='True') "@ | Select-Object ` @{Name='GroupName'; Expression={($_.GroupComponent -split 'Name="')[1] -split '"' | Select-Object -First 1}}, @{Name='UserName'; Expression={($_.PartComponent -split 'Name="')[1] -split '"' | Select-Object -First 1}} | Format-List
这个查询会直接返回所有本地组中的本地用户,并且通过计算属性把冗长的WMI路径转换成清晰的GroupName和UserName字段。
解决方案2:用Get-CimAssociatedInstance分步查询(更直观)
先获取所有本地组,再逐个获取每个组关联的用户并筛选本地用户:
# 获取所有本地组 $localGroups = Get-CimInstance -ClassName Win32_Group -Filter "LocalAccount='True'" # 遍历每个组,获取关联的本地用户 foreach ($group in $localGroups) { $localUsersInGroup = Get-CimAssociatedInstance -InputObject $group -ResultClassName Win32_UserAccount | Where-Object { $_.LocalAccount -eq $true } # 输出结果 foreach ($user in $localUsersInGroup) { [PSCustomObject]@{ GroupName = $group.Name UserName = $user.Name } } } | Format-List
这个方法逻辑更直白,适合需要在中间步骤添加额外处理(比如过滤特定组)的场景。
集成到Ansible Playbook
要在多台远程Windows服务器上运行,用win_powershell模块执行上述PowerShell代码即可。示例Playbook如下:
- name: Retrieve local users in local groups on Windows servers hosts: windows_servers gather_facts: false tasks: - name: Run PowerShell query to get local group members win_powershell: script: | Get-CimInstance -Query @" SELECT GroupComponent, PartComponent FROM Win32_GroupUser WHERE GroupComponent IN (SELECT __PATH FROM Win32_Group WHERE LocalAccount='True') AND PartComponent IN (SELECT __PATH FROM Win32_UserAccount WHERE LocalAccount='True') "@ | Select-Object @{Name='GroupName'; Expression={($_.GroupComponent -split 'Name="')[1] -split '"' | Select-Object -First 1}}, @{Name='UserName'; Expression={($_.PartComponent -split 'Name="')[1] -split '"' | Select-Object -First 1}} register: local_group_members - name: Display the results debug: var: local_group_members.output
执行这个Playbook后,local_group_members.output会包含每台服务器上本地组和对应本地用户的列表。
内容的提问来源于stack exchange,提问作者Raphael
相关产品推荐
相关产品推荐

