如何浓缩此PowerShell脚本?

问题描述:

如果用户在某个AD组中并且连接到某个网络,我正在创建一个代码以打开网站。这是我这么远:如何浓缩此PowerShell脚本?

$user = $env:username 
$group1 = "examplegroup1" 
$group2 = "examplegroup2" 

if (Test-Connection "examplenetwork" -Quiet) 
{  
$members1 = Get-ADGroupMember -Identity $group1 | Select -ExpandProperty 
SamAccountName 

$members2 = Get-ADGroupMember -Identity $group2 | Select -ExpandProperty 
SamAccountName 

If ($members1 -contains $user -or $members2 -contains $user) {Start-Process 
"examplewebsite"} 
} 

它的工作原理,因为它应该打开网站,如果用户是在正确的组,并在网络上,但是我如果有凝结的方式只是想知道代码?

看起来很浪费必须创建2'$groups',然后重复Get-ADGroupMember也是。我曾经玩过“ForEach”,但还没有成功实现它。

关于如何浓缩这个的任何想法?最好使用ForEach cmdlet。

+2

我正在投票结束这个问题作为题外话,因为工作代码是脱离主题,并且SE网站审查/建议对工作代码的更改是https://codereview.stackexchange.com/ – TessellatingHeckler

+1

您还假设最终用户的计算机将安装AD模块。如果您将其设计为登录脚本,您将遇到该问题。 –

虽然我其他的答案是“不这样做”,如果你想你的代码,凝聚:

$groups = 'group1', 'group2' 

if ((Test-Connection -ComputerName "examplenetwork" -Quiet) -and 
    ($env:USERNAME -in ($groups | Get-ADGroupMember -Recursive).SamAccountName)) 
{ 
    Start-Process "www.example.com" 
} 

你真不不需要任何foreach。

+1

谢谢,TessellatingHeckler。这是我正在寻找的。我对Powershell非常陌生(正如你可能知道的那样),管道是我需要增加知识的一件事!至于公元问题......我将不得不在明天解决这个问题!再次感谢。 – Powershelln00b

您可以添加一个foreach循环,但会使已经非常小巧简单的脚本复杂化。

我做的最多的就是来自这两个组一起添加成员...

$user = $env:username 
$group1 = "examplegroup1" 
$group2 = "examplegroup2" 

if (Test-Connection "examplenetwork" -Quiet) 
{  
    $members = Get-ADGroupMember -Identity $group1 | Select -ExpandProperty SamAccountName 

    $members += Get-ADGroupMember -Identity $group2 | Select -ExpandPropertySamAccountName 

    If ($members -contains $user) {Start-Process "http://www.example.com"} 
} 
+0

这不能解决“*重复Get-ADGroupMember *”部分似乎很浪费的问题,但它确实改变了它,因此如果Group1只有一个成员,它现在会中断。 – TessellatingHeckler

If (("examplegroup1", "examplegroup2" | % {Get-ADGroupMember -Identity $_} | Select -ExpandProperty SamAccountName) -Contains $env:username) {Start-Process "examplewebsite"} 
+0

如果用户包含在两个组中,则可以启动该过程两次。 – TToni

+0

@ TToni:不,'-unique'参数应该可以防止这个问题 – iRon

+0

事实上,'-unique'甚至不需要(我已经将它从答案中删除了),如下所示:If( -contains $ env :username){}即使包含重复成员,也不会再运行给定的''。 – iRon

我可能会做反向:

$user = $env:username 
$groups = "examplegroup1", "examplegroup1" 

$CheckMembership = Get-ADUser -Identity $user -Property MemberOf | Select-Object -ExpandProperty MemberOf | Where-Object { $_ -in $groups } 

if ($CheckMembership) { 
    Start-Process "http://www.example.com" 
} 

你会想请确保您的组列表是可分辨名称的列表,但除此之外,这会将AD查询的数量减少到1.

任何依靠Get-AD___需要RSAT工具才能获得ActiveDirectory模块,对于最终用户工作站来说这是不太可能的假设,正如@Rohin Sidharth所评论的。

@詹姆斯C.目前接受的答案不会处理递归组成员(需要参数-Recursive),但也包括列出两个组的所有成员 - 想象一下,如果每个组的成员数为十亿 - 并且它有阵列增加的不良习惯。

@Bacon位答案获取用户的组成员资格,这对于'获取更少的数据'更好,但仍然不会处理递归组成员资格,仍然依赖于ActiveDirectory模块。

为避免RSAT,可以使用类似ADSI的东西 - 它由System.DirectoryServices.AccountManagement包装。 Richard Siddaway讨论了here

这有一个很好的方法来列出用户的组成员,这似乎是坏的 - 从Terry Tsay的C#答案捏here,我将他的代码移植到此,但我专注于当前用户和默认包含的通讯组:

Add-Type -AssemblyName System.DirectoryServices.AccountManagement 

Function IsUserInGroup([string] $groupName) 
{ 
    # Remove DOMAIN\ from the start of the groupName. 
    $groupName = $groupName -replace '^.*\\' 


    # Get an AD context for the current user's domain 
    $context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList 'Domain', $ENV:USERDOMAIN 


    # Find the current user account in AD, and refresh the security and distribution groups 
    $user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($context, 'SAMAccountName', $env:USERNAME) 
    $userEntry = [System.DirectoryServices.DirectoryEntry] $user.GetUnderlyingObject() 
    $userEntry.RefreshCache(@('tokenGroupsGlobalAndUniversal')) 


    # Get all the security and distribution groups the user belongs to, including nested memberships 
    $usersGroupSIDs = foreach ($sid in $userEntry.Properties.tokenGroupsGlobalAndUniversal.Value) 
    { 
     New-Object System.Security.Principal.SecurityIdentifier -ArgumentList $sid, 0 
    } 


    # Get the AD details for the group to test, and test membership 
    $group = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($context, 'SamAccountName', $groupName) 

    $usersGroupSIDs.Contains($group.Sid) 
} 

eg

PS C:\> IsUserInGroup 'parent-nested-group-here' 
True 

这是不凝结或者更简单,但它应该用更少的开销AD连接尤其是作为组成员的增加数,以及额外的模块不太需要,只是使用.NET Framework处理更多的条件。

然后,你可以修改,这样做

$group2 = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($context, 'SamAccountName', $group2Name) 

$usersGroupSIDs.Contains($group.Sid) -or $usersGroupSIDs.Contains($group2.Sid)