从 ADUser DistinguishedName 获取 CN 值

Get CN value from ADUser DistinguishedName

我有一个 PS 脚本可以检查 Active Directory 中的某些自定义用户的属性。 其中一个属性是“经理”。

 $data = Get-ADUser $user -Properties * |  Select-Object DisplayName, LockedOut, Enabled, LastLogonDate, PasswordExpired, EmailAddress, Company, Title, Manager, Office

 Write-Host "9." $user "manager is" $data.manager -ForegroundColor Green

当我 运行 我得到的脚本时:

User's manager is CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com

问题是某些用户的文本 "OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com" 会有所不同

如何修改输出并删除 "cool.boss" 以外的所有内容? 提前谢谢你

您可以为此使用正则表达式:

$s = "CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC =com"

$pattern = [regex]"CN=.*?OU"
$r = $pattern.Replace($s, "CN=OU")
$r

您可以使用.split()方法来获得您想要的。

$DN = "CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC =com"
$DN.Split(',').Split('=')[1]

我的建议是将其放入另一个 Get-ADUser 以获得更整洁的输出的显示名称(:

这应该是一种或多或少安全且仍然易于解析的方法:

($data.manager -split "," | ConvertFrom-StringData).CN

使用 PowerShell 惯用的 regex 解决方案来补充此处的有用答案:

$dn = 'CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com'

($dn -split '(?:^|,)CN=|,')[1] # -> 'cool.boss'
  • 使用 -replace,基于正则表达式的 :
$dn = 'CN=cool.boss,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com'

$dn -replace '(?:^|,)CN=([^,]+).*', '' # -> 'cool.boss'

注:

  • 上述解决方案不依赖于输入中名称-值对 (RDN) 的特定顺序(即 CN 条目不必是 first 一个),但他们只提取 first CN 条目的值,如果存在多个,他们确实假设(在至少)一个存在。

  • 原则上,DNs (Distinguished Names),以输入字符串为例,值中可以有,个字符嵌入构成 DN 的名称-值对的数量,转义为 \,(或者,以十六进制表示法,C);例如,"CN=boss\, cool,OU=Users,..."

  • 一个真正强大的解决方案必须考虑到这一点,并且理想情况下也会 unescape 结果值; none 的现有答案在撰写本文时这样做;见下文。


稳健地解析 LDAP/AD DN (Distinguished Name):

以下Split-DN函数:

  • 正确处理转义、嵌入 , 个字符以及其他转义序列
  • unescapes 值,这不仅包括删除句法 \,还包括将转义序列转换为 \<hh> 形式,其中 hh 是一个两位数的十六进制。代表字符代码点的数字,转换为它们代表的实际字符(例如,C,转换为 < 字符)。
  • 输出一个有序的hashtable,其键是名称组件(例如,CNOU),名称的值出现多个 次 - 例如 OU - 表示为 数组 .

调用示例:

PS> Split-DN 'CN=I C3 Huckabees\, I do,OU=Users,OU=SO,OU=PL,OU=RET,OU=HBG,DC=domain,DC=com'

Name                           Value
----                           -----
CN                             I <3 Huckabees, I do
OU                             {Users, SO, PL, RET…}
DC                             {domain, com}

注意转义序列 C 如何转换为 <,它代表的字符,以及 \, 如何被识别为 , 嵌入CN 值中。

由于输入字符串包含 多个 OUDC 名称-值对(所谓的 RDN,relative distinguished names),它们对应的哈希表条目变成了 arrays 个值(在 truncated-for-display-only 输出中用 { ... } 表示,用 ,分离元素)。


函数Split-DN的源代码:

注意:为简洁起见,省略了错误处理和验证。

function Split-DN {

  param(
    [Parameter(Mandatory)]
    [string] $DN
  )

  # Initialize the (ordered) output hashtable.
  $oht = [ordered] @{}

  # Split into name-value pairs, while correctly recognizing escaped, embedded
  # commas.
  $nameValuePairs = $DN -split '(?<=(?:^|[^\])(?:\\)*),'

  $nameValuePairs.ForEach({

    # Split into name and value.
    # Note: Names aren't permitted to contain escaped chars.
    $name, $value = ($_ -split '=', 2).Trim()

    # Unescape the value, if necessary.
    if ($value -and $value.Contains('\')) {
      $value = [regex]::Replace($value, '(?i)\(?:[0-9a-f]){2}|\.', {
        $char = $args[0].ToString().Substring(1)
        if ($char.Length -eq 1) { # A \<literal-char> sequence.
          $char # Output the character itself, without the preceding "\"
        }
        else { # A \<hh> escape sequence, conver the hex. code point to a char.
          [char] [uint16]::Parse($char, 'AllowHexSpecifier') 
        }
      })
    }
    
    # Add an entry to the output hashtable. If one already exists for the name,
    # convert the existing value to an array, if necessary, and append the new value.
    if ($existingEntry = $oht[$name]) {
      $oht[$name] = ([array] $existingEntry) + $value
    }
    else {
      $oht[$name] = $value
    }

  })

  # Output the hashtable.
  $oht
}