我正尝试通过一组组循环所有禁用的用户,以检查用户是否具有列出的任何组的成员身份。我的想法是,对于列表中的每个用户,请他们进行遍历,并检查它们是否在列出的组之一中。那将需要嵌套foreach
循环,对吗?我得到的输出是这样的:
... user1 user2 user3 is not a member of group1
这是源代码:
$dUsers = Get-ADUser -Filter {enabled -eq $false} |
FT samAccountName |
Out-String
$groups = 'Group1', 'Group2'
foreach ($dUser in $dUsers) {
foreach ($group in $groups) {
$members = Get-ADGroupMember -Identity $group -Recursive |
Select -ExpandProperty SamAccountName
if ($members -contains $dUsers) {
Write-Host "[+] $dUser is a member of $group"
} else {
Write-Host "[-] $dUser is not a member of $group"
}
}
}
我拉头发是因为我觉得有一个简单的解决方案,但我迷路了。
更新:
我想将所有禁用的用户放在变量$dUsers
中。
如果我手动将用户放在这样的变量中,它实际上会起作用:
$dUsers = 'user1','user2','user3'
哪个给我以下输出:
user1 is not a member of group1 user1 is not a member of group2 user2 is not a member of group1 user2 is not a member of group2 ...
这使我感到疑问,当变量为:
$dUsers = Get-ADUser -Filter {enabled -eq $false} |
FT samAccountName |
Out-String
有人对此有澄清吗?
更新:
这是最终代码。即使只有两个组,运行也要花费很长时间。
$dUsers = Get-ADUser -Filter {enabled -eq $false} | Select-Object -Expand SamAccountName
$groups = 'Group1', 'Group2'
Write-host '[+] Checking if any disabled user is member of any SSL groups'
Write-host '[+] This might take a while. Get a coffee!'
write-host '[+] Running...'`n
foreach ($dUser in $dUsers) {
foreach ($group in $groups) {
$members = Get-ADGroupMember -Identity $group -Recursive | Select -ExpandProperty SamAccountName
if($members -contains $dUser) {
Write-Host "$dUser is a member of $group"
} Else {
# Remove or comment out the line below to get a clutterfree list.
# Write-Host "$dUser is not a member of $group"
}
}
}
答案 0 :(得分:1)
根据您所使用的PowerShell版本,此用例和其他用例都有一个cmdlet。
至
我正在尝试循环所有禁用的用户
就做...
Search-ADAccount -AccountDisabled |
Select-Object -Property Name, Enabled,
@{Name = 'GroupName';Expression = {$_.DistinguishedName.Split(',')[1] -replace 'CN='}}
# Results
Name Enabled GroupName
---- ------- ---------
...
testuser2 NewTest False Users
Guest False Users
或其他cmdlet ...
# Get disabled users and their group membership, display user and group name
ForEach ($TargetUser in (Get-ADUser -Filter {Enabled -eq $false}))
{
"`n" + "-"*12 + " Showing group membership for " + $TargetUser.SamAccountName
Get-ADPrincipalGroupMembership -Identity $TargetUser.SamAccountName | Select Name
}
# Results
...
------------ Showing group membership for testuser1
Domain Users
Users
------------ Showing group membership for testuser2
Domain Users
关于...
一组分组
只需使用常规比较运算符为所需的组名称选择或过滤DN。
至于...
不幸的是,我对Powershell并不熟悉。
...请务必花费必要的时间来逐步完善它,以限制将要遇到的误解,困惑,错误等。在网上有很多免费的免费视频/基于文本的培训/演示文稿。
示例: Videos
使用可为您编写代码的工具,您以后可以根据需要对其进行调整。
Step-By-Step: Utilizing PowerShell History Viewer in Windows Server 2012 R2
Learning PowerShell with Active Directory Administrative Center (PowerShell History Viewer)
以及大量示例脚本和模块答案 1 :(得分:1)
您的代码中有两个问题:
您正在从Get-ADUser
输出中创建一个字符串。通过Format-Table
(别名为ft
)输入该cmdlet的输出,然后Out-String
创建一个字符串,并以表格形式显示所有匹配的帐户名,包括表头。
如果您以使字符串的开头和结尾可见的方式输出$dUsers
,您会看到类似这样的内容(开头和结尾的==
标记了开头和结尾):
PS> $dUsers | ForEach-Object { "==$_==" } ==samAccountName -------------- user1 user2 user3==
由于没有用户名与该字符串匹配的帐户,因此在任何组中都找不到匹配项,您将获得观察到的输出。
这种Format-*
cmdlet的滥用是一个常见的初学者错误。人们得到了格式正确的字符串输出,然后尝试使用它。仅在将数据直接呈现给用户时使用Format-*
cmdlet,而在需要或打算进一步处理数据时则永远不要使用。{p>
您真正想要的不是以用户名列表形式显示的字符串,而是用户名字符串的数组。通过扩展从SamAccountName
获得的用户对象的Get-ADUser
属性,可以实现这一点。
$dUsers = Get-ADUser ... | Select-Object -Expand SamAccountName
第二个问题可能只是拼写错误。您的条件$members -contains $dUsers
将不起作用,因为$members
和$dUsers
都是数组(就是在解决第一个问题之后)。 -contains
运算符期望将数组作为第一个操作数,并将单个值作为第二个操作数。
更改
$members -contains $dUsers
到
$members -contains $dUser
答案 2 :(得分:0)
有两个用于AD组的命令。 首先,我看到您想要轻松地成为残疾用户的成员。
#Get the dissabled users from your AD with all their attributes (properties and select)
$dUsers = Get-ADUser -Filter {Enabled -eq $false} -Properties * | Select *
#Run a loop for each user to get the group membership
Foreach ($User in $dUsers) {
$User = $User.SamAccountName
Get-ADUser $User -Properties * | Select Name, SamAccountName, MemberOf | Format-Table -Wrap # > "D:\test\$user.txt" -HideTableHeaders
}
这可以工作,但我不喜欢我们得到的输出。 我更喜欢运行groupmembership命令并检查用户。
$GroupMembers = Get-ADGroupMember "groupname"| Select Name, SamAccountName
ForEach ($User in $GroupMembers)
{
$UserProperties = Get-ADUser $User.SamAccountName -Properties * | select *
If ($UserProperties.Enabled -eq $False) {
Write-Host $UserProperties.SamAccountName
}
}
编辑:
让我知道是否适合您。 此致。
答案 3 :(得分:0)
您应该尝试检查的第一件事是,只要您只对直接成员身份或对间接成员身份感兴趣。根据答案,您可以使用的选项有些变化。在进行此操作时,您可能会遇到Distinguished Names,所以如果不知道(主要是对象的路径),请检查它们是什么。
如果仅是直接成员资格,则将memberOf
与Get-ADUser
配合使用就足够了。 memberOf
属性包含用户的每个直接组成员身份以及该组的完整专有名称。
Get-ADUser test -Properties MemberOf | Select-Object -ExpandProperty memberOf
您可以通过多种方式匹配您要寻找的组。您可以获取这些组的完整专有名称,也可以进行部分匹配。由您决定如何进行。
如果您还需要间接成员身份,则可能需要拆分代码以使其更容易使用。例如,您可以首先找到用户并保存。然后找到这些组的所有组成员(您已经使用Get-ADGroupMember
了),最后将两者进行比较。
当前,您将为每个用户再次构建整个组成员列表。这种方法将节省一些资源,因为您不会一遍又一遍地执行相同的查询。
最后,您还可以使用MemberOf
方法,但是使用LDAP查询获得用户的每个直接和间接成员资格的列表。
$dn = (Get-ADUser example).DistinguishedName
$userGroups = Get-ADGroup -LDAPFilter ("(member:1.2.840.113556.1.4.1941:={0})" -f $dn)
此方法使用LDAP search query。这可能非常复杂,您也可以只通过稍微修改一下来检查其中一个组。
最后,即使您当前的方法也应该可行。问题在于您正在将AD对象与SAM帐户名列表进行比较。您还需要检查SAM帐户名。
if($members -contains $dUsers.SamAccountName)
if($members -contains $dUsers | Select-Object -ExpandProperty SamAccountName)
如果您也更改了$dUsers
,则其中之一应该起作用。由于当前情况,您最终会遇到一条巨大的弦。您可能可以通过选中$dUsers.length
进行检查。只需放下Format-Table
和Out-String
。