【问题标题】:Need to add a step for unexpected results需要为意外结果添加一个步骤
【发布时间】:2019-10-05 02:59:18
【问题描述】:

我有一个脚本可以运行并告诉我用户是否属于特定的 AD 组,该组将识别他正在使用的 VPN。当脚本遇到不属于域的用户时,它会中断并且不再继续,我想寻求帮助,以添加一个将在输出文件中打印出该用户不在系统中的片段,并且继续检查其余部分。

此外,当我只为我知道在系统中的用户运行它时,它会将他们的名字多次放入他们不属于的 AD 组中。

Get-Content D:\Scripts\VPNGroup\List1.txt | Foreach-Object {
   $name =  ( ( net user $_ /domain | select-string 'full name' | out-string ).Trim() -split "`r`n" ) |
      Foreach-Object { $_.Substring(29).Trim() -split 'full name' } |
      Where-Object { -Not [String]::IsNullOrWhiteSpace($_) } 
      $group =  ( ( net user $_ /domain | select-string '\*' | out-string ).Trim() -split "`r`n" ) |
      Foreach-Object { $_.Substring(29).Trim() -split '\*' } |
      Where-Object { -Not [String]::IsNullOrWhiteSpace($_) } 
      $group >> D:\Scripts\VPNGroup\FullList.txt


   $ADgroups = Get-Content D:\Scripts\VPNGroup\FullList.txt

   $VPNgroups = foreach($line in $ADgroups) {
       if ($line -like "VPN-GRP*") {$name + $line >> D:\Scripts\VPNGroup\ADGroups.txt}

   }
}

这是当用户不在系统中时我得到的输出:

net : The user name could not be found.
At line:2 char:17
+    $name =  ( ( net user $_ /domain | select-string 'full name' | out-string ).T ...
+                 ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (The user name could not be found.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

More help is available by typing NET HELPMSG 2221.
Exception calling "Substring" with "1" argument(s): "startIndex cannot be larger than length of string.
Parameter name: startIndex"
At line:3 char:24
+       Foreach-Object { $_.Substring(29).Trim() -split 'full name' } |
+                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException

当它们在系统中时,我会用错误的信息 IE 获取它们:

迈克尔·史密斯 VPN-GRP-1
迈克尔·史密斯 VPN-GRP-1
迈克尔·史密斯 VPN-GRP-1
迈克尔·史密斯 VPN-GRP-1
迈克尔·史密斯 VPN-GRP-1
迈克尔·史密斯 VPN-GRP-2
迈克尔·史密斯 VPN-GRP-2
迈克尔·史密斯 VPN-GRP-2
迈克尔·史密斯 VPN-GRP-2
迈克尔·史密斯 VPN-GRP-2
迈克尔·史密斯 VPN-GRP-3
迈克尔·史密斯 VPN-GRP-3
迈克尔·史密斯 VPN-GRP-3
贾斯汀·琼斯 VPN-GRP-1
贾斯汀·琼斯 VPN-GRP-1
贾斯汀·琼斯 VPN-GRP-1
贾斯汀·琼斯 VPN-GRP-1
贾斯汀·琼斯 VPN-GRP-2
贾斯汀·琼斯 VPN-GRP-2
贾斯汀·琼斯 VPN-GRP-3
贾斯汀·琼斯 VPN-GRP-3
贾斯汀·琼斯 VPN-GRP-3
贾斯汀·琼斯 VPN-GRP-3
贾斯汀·琼斯 VPN-GRP-4
......继续为超过 1k 用户提供服务
每个用户只是其中一个 AD 组的成员。

【问题讨论】:

  • 您为什么不只使用 AD cmdlet?获取组的成员,然后根据它执行查找不是更简单吗?
  • 我正在使用的系统是 DMZed 并且没有 Active Directory 模块:/

标签: powershell scripting active-directory


【解决方案1】:

这里的问题是,对于每个用户,您都将他们的组附加到 FullList.txt。因此,对于每个人,您也要对照之前每个人的组进行检查。

我要做的第一个调整是将 net user 的输出存储到一个变量中,这样您就不必多次运行它,使用 $Query = cmd /c net user 'asdf' /domain 2>&1 完成。

接下来,我们将检查它是否在 if 语句中找到了有效用户:

if ( $Query | Select-String 'The user name could not be found.') {
    "$_ is not a valid user" | Out-File -FilePath D:\Scripts\VPNGroup\ADGroups.txt -Append
  }

否则,如果它是有效用户,那么我们可以继续执行脚本的其余部分并提取名称和组。我冒昧地简化了一些代码,并使用正则表达式来获取名称。

$Query | Where-Object { $_ -match 'Full\sName\s+(\w+\s\w+)' } 
    $name = $Matches[1]

    $groups = $Query | select-string '\*' | Out-String |
    ForEach-Object { $_.Substring(29).Trim() -split '\*' -split "`r`n" } |
    Where-Object { -Not [String]::IsNullOrWhiteSpace($_) }

我删除了它输出到文件的步骤,然后脚本再次读取该文件,这似乎是多余的。但最后我们检查其中一个组是否与 VPN 字符串匹配:

foreach ($group in $groups) {
    if ($group -like 'VPN-GRP*') { $name + $group | Out-File 'D:\Scripts\VPNGroup\ADGroups.txt' -Append }

应该这样做。让我知道我是否搞砸了,或者它仍然无法正常工作。以下是它的整体外观:

Get-Content D:\Scripts\VPNGroup\List1.txt | Foreach-Object {
  $Query = cmd /c net user $_ /domain 2`>`&1
  if ( $Query | Select-String 'The user name could not be found.') {
    "$_ is not a valid user" | Out-File -FilePath D:\Scripts\VPNGroup\ADGroups.txt -Append
  }
  else {
    $Query | Where-Object { $_ -match 'Full\sName\s+(\w+\s\w+)' } 
    $name = $Matches[1]

    $groups = $Query | select-string '\*' | Out-String |
    ForEach-Object { $_.Substring(29).Trim() -split '\*' -split "`r`n" } |
    Where-Object { -Not [String]::IsNullOrWhiteSpace($_) }

    foreach ($group in $groups) {
      if ($group -like 'VPN-GRP*') { $name + $group | Out-File 'D:\Scripts\VPNGroup\ADGroups.txt' -Append }
    }
  }
}

【讨论】:

  • 此脚本仅在完成时输出最后一个签入 ADGroups 文本文件的用户 ID。
  • 你说得对,我错过了将 -Append 添加到组 Out-File 命令。不过我现在修好了!
  • 我做了同样的事情并将其添加到脚本中,它现在可以工作了。谢谢
【解决方案2】:

如果是我,我会针对域控制器进行 ADSI 搜索。不需要 AD cmdlet。

$Groups = 'VPN-GRP-1','VPN-GRP-2','VPN-GRP-3','VPN-GRP-4'
$GroupHT = @{}
$LDAP = "DC=domain,DC=com"

ForEach($Group in $Groups){
    $Filter = "(&(sAMAccountName=$Group)(objectClass=group))"
    $Searcher = [adsisearcher]$Filter
    $Searcher.SearchRoot = "LDAP://$LDAP"
    $Searcher.PropertiesToLoad.Add('Member')|Out-Null
    $Results=$Searcher.FindAll()
    $Members=ForEach($User in $Results.Properties.Item('member')){
        $LDAP = $User -replace '^.+?,(?=DC=)'
        $Filter = "(&(DistinguishedName=$User)(objectClass=user))"
        $Searcher = [adsisearcher]$Filter
        $Searcher.SearchRoot = "LDAP://$LDAP"
        $Searcher.PropertiesToLoad.Add('SamAccountName')|Out-Null
        $UserResults=$Searcher.FindAll()
        $objProps=@{SamAccountName=$UserResults.Properties.Item('SamAccountName');FullName=$User -replace "CN=(.+?),.*",'$1'}
        New-Object PSObject -Property $objProps
    }
    $GroupHT.Add($Group,$Members)
}

$Results=ForEach($User in (Get-Content D:\Scripts\VPNGroup\List1.txt)){
    $UserInfo = $GroupHT.GetEnumerator()|?{$User -in $_.Value.SamAccountName}|%{"{0} {1}" -f ($_.Value|?{$_.SamAccountName -eq $User).FullName,$_.Key}
    If(![string]::IsNullOrWhitespace($UserInfo)){$UserInfo}Else{Write-Warning "User not found in a group: $user"}
}
$Results | Add-Content 'D:\Scripts\VPNGroup\ADGroups.txt'

这将为您留下一个以组名作为键的哈希表,以及一个包含每个组成员的 FullName 和 SamAccountName 的对象数组。然后它遍历用户,引用哈希表来查找他们的组,如果没有找到,则向屏幕输出警告。最后,它将所有找到的用户添加到一个文件中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-11
    • 2013-11-28
    相关资源
    最近更新 更多