You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何改进PowerShell函数以返回ADObject的全部可用属性?

问题:验证AD域对象属性可用性的函数改进

我需要查询多个域的用户数据,由于不同域的配置和功能存在差异,因此在执行查询前,我希望验证所需返回的属性是否在目标域中可用,以避免执行过程中出现错误。

为此我编写了如下函数:

function Get-ADDomainSupportedProperty {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$Server = $Env:USERDNSDOMAIN,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$ObjectType = "User",

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string[]]$Property
    )

    # Get all available properties in the domain
    $params = @{
        SearchBase = (Get-ADRootDSE -Server $Server).SchemanamingContext
        Filter     = { Name -eq $ObjectType }
        Server     = $Server
        Properties = "*"
    }
    $allProperties = Get-ADObject @params
    
    # Select all default properties
    $allDefaultProperties  = $allProperties | 
                                Get-Member -MemberType "Properties" |
                                Select-Object -ExpandProperty Name |
                                Where-Object { $_ -notin @("MayContain", "SystemMayContain") }
    # Select all extended properties
    $allExtendedProperties = $allProperties | 
                                Select-Object @{ Name = "Properties"; Expression = { $_.MayContain + $_.SystemMayContain }} |
                                Select-Object -ExpandProperty "Properties"

    $allAvailableProperties = $allDefaultProperties + $allExtendedProperties | Sort-Object -Unique

    # Return available properties
    if ($Property) {
        $Property | Where-Object { $_ -in $allAvailableProperties }
    } else {
        $allAvailableProperties
    }
}

该函数基本能按预期工作,可返回扩展属性数组,但无法返回部分默认属性(例如sn或Company)。请问有谁能提供改进建议,让我的函数可以返回所有可用属性?

编辑

在社区帮助下,以下是最终版函数,供有需要的人使用:

<#
    .SYNOPSIS
        检索指定Active Directory对象类型支持的属性。

    .DESCRIPTION
        Get-ADDomainSupportedAttribute函数检索指定Active Directory对象类型支持的属性。
        你可以指定服务器、对象类型和要检索的属性,也可以选择只检索必填或可选属性。

    .PARAMETER Server
        要连接的服务器,默认为当前用户的DNS域。

    .PARAMETER ObjectType
        要检索属性的Active Directory对象类型,默认为"User"。

    .PARAMETER Attribute
        要检索的特定属性,属于Attribute参数集。

    .PARAMETER MandatoryOnly
        仅检索必填属性的开关,属于Mandatory参数集。

    .PARAMETER OptionalOnly
        仅检索可选属性的开关,属于Optional参数集。

    .EXAMPLE
        PS> Get-ADDomainSupportedAttribute -Server "dc.domain.local" -ObjectType "User"
        检索指定服务器上"User"对象类型的所有支持属性。

    .EXAMPLE
        PS> Get-ADDomainSupportedAttribute -ObjectType "Computer" -MandatoryOnly
        仅检索"Computer"对象类型的必填属性。

    .EXAMPLE
        PS> Get-ADDomainSupportedAttribute -Attribute "cn", "sn"
        检索指定属性"cn"和"sn"。

    .NOTES
        在社区帮助下创建
#>

# 模块作用域的哈希表,用于缓存每个服务器的架构信息
$schemaCache = @{}

function Get-ADDomainSupportedAttribute {
    [CmdletBinding(DefaultParameterSetName = "Default")]
    param (
        [Parameter(Mandatory = $false, ParameterSetName = "Default")]
        [Parameter(Mandatory = $false, ParameterSetName = "Attribute")]
        [Parameter(Mandatory = $false, ParameterSetName = "Mandatory")]
        [Parameter(Mandatory = $false, ParameterSetName = "Optional")]
        [ValidateNotNullOrEmpty()]
        [string]$Server = $env:USERDNSDOMAIN,

        [Parameter(Mandatory = $false, ParameterSetName = "Default")]
        [Parameter(Mandatory = $false, ParameterSetName = "Attribute")]
        [Parameter(Mandatory = $false, ParameterSetName = "Mandatory")]
        [Parameter(Mandatory = $false, ParameterSetName = "Optional")]
        [ValidateNotNullOrEmpty()]
        [string]$ObjectType = "User",

        [Parameter(Mandatory = $false, ParameterSetName = "Attribute")]
        [ValidateNotNullOrEmpty()]
        [string[]]$Attribute,

        [Parameter(Mandatory = $false, ParameterSetName = "Mandatory")]
        [switch]$MandatoryOnly,

        [Parameter(Mandatory = $false, ParameterSetName = "Optional")]
        [switch]$OptionalOnly
    )

    # 如果当前服务器不在缓存中,添加到缓存
    if (-not $script:schemaCache.ContainsKey($Server)) {
        $classSchemaSearchParams = @{
            SearchBase = (Get-ADRootDSE -Server $Server).schemaNamingContext
            Server     = $Server
            Filter     = { objectClass -eq "classSchema" }
            Properties = "lDAPDisplayName", "auxiliaryClass", "systemAuxiliaryClass", "mayContain", "systemMayContain", "mustContain", "systemMustContain", "subClassOf"
        }

        $allClassSchemas = @{}
        Get-ADObject @classSchemaSearchParams | ForEach-Object { $allClassSchemas[$_.lDAPDisplayName] = $_ }

        $script:schemaCache[$Server] = $allClassSchemas
    }

    # 从缓存中获取架构表
    $allClassSchemas = $script:schemaCache[$Server]

    # 用于跟踪发现的属性和已解析的类的数组
    $mayBag   = @()
    $mustBag  = @()
    $resolved = @()

    [array]$unresolved = @($ObjectType)

    while ($unresolved.Count) {
        # 选择下一个要解析属性和关系的类名
        $next, $unresolved = $unresolved

        if (-not $allClassSchemas.ContainsKey($next)) {
            Write-Error "未找到LDAP显示名为'${next}'的类架构"
            return
        }

        # 查找给定类的架构对象
        $nextSchema = $allClassSchemas[$next]

        # 确保不重复工作或进入循环
        if ($nextSchema.lDAPDisplayName -in $resolved) { continue }

        # 获取与当前类架构关联的属性
        $mayBag += @(
            $nextSchema.mayContain
            $nextSchema.systemMayContain
        )
        $mustBag += @(
            $nextSchema.mustContain
            $nextSchema.systemMustContain
        )

        # 除非架构指向自身(top类),否则将父类加入解析队列
        if ($nextSchema.subClassOf -and $nextSchema.subClassOf -ne $nextSchema.lDAPDisplayName) {
            $unresolved += $nextSchema.subClassOf
        }

        # ...然后加入辅助类
        if ($nextSchema.auxiliaryClass) {
            $unresolved += @($nextSchema.auxiliaryClass)
        }
        if ($nextSchema.systemAuxiliaryClass) {
            $unresolved += @($nextSchema.systemAuxiliaryClass)
        }

        # ...最后将当前架构添加到已解析类列表中
        $resolved += $nextSchema.lDAPDisplayName
    }

    # 返回可用属性
    if ($Attribute) {
        # 仅返回$Attribute参数中指定的属性名
        $Attribute | Where-Object { $_ -in $mayBag + $mustBag | Sort-Object -Unique }
    } elseif ($MandatoryOnly) {
        # 仅返回必填属性名
        $mustBag | Sort-Object -Unique
    } elseif ($OptionalOnly) {
        # 仅返回可选属性名
        $mayBag | Sort-Object -Unique
    } else {
        # 返回所有属性名
        $mayBag + $mustBag | Sort-Object -Unique
    }
}

内容的提问来源于stack exchange,提问作者TheBrickAdmin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 19:04:55