PowerShell是否有办法在选择对象中获得正确的属性顺序,以便每个对象都有顺序?

PowerShell是否有办法在选择对象中获得正确的属性顺序,以便每个对象都有顺序?,powershell,Powershell,下面的代码列出了所有广告用户 $Domain.DomainUsersFullList = Get-ADUser -Server $Domain -ResultPageSize 500000 -Filter * -Properties *, "msDS-UserPasswordExpiryTimeComputed" | Select * -ExcludeProperty *Certificate, PropertyNames, *Properties, PropertyCount, Certifi

下面的代码列出了所有广告用户

$Domain.DomainUsersFullList = Get-ADUser -Server $Domain -ResultPageSize 500000 -Filter * -Properties *, "msDS-UserPasswordExpiryTimeComputed" | Select * -ExcludeProperty *Certificate, PropertyNames, *Properties, PropertyCount, Certificates
$($Domain.DomainUsersFullList[0]).PSObject.Properties.Name[12]
$($Domain.DomainUsersFullList[10]).PSObject.Properties.Name[12]
似乎
PSObject.Properties.Name
返回的顺序可能不同。有没有一种方法可以对属性进行排序,而不必专门告诉
Select Object
所需的顺序

只是为了我为什么需要这个:

  • -我编写了一个函数
    addwordtable
    ,它接受任何
    $Object
    ,并将其放入Word文档中。不需要自己解析对象。只需将其传递给函数,它就会被放入Word文档中
我现在也在做同样的事情:

  • -其功能为添加ExcelWorksheetData,除一个例外,与上述功能完全相同。。因为它是Excel,所以没有列限制。因此,对于100列,每行的顺序都是错误的。这毫无意义
而对于WORD文档,我没有注意到这个问题,因为我从来没有添加超过10列,而Excel和100列的顺序是错误的。下面是一个例子:

以下是进行转换的方法:

function Format-PSTableConvertType2 {
    [CmdletBinding()]
    param(
        $Object,
        [switch] $SkipTitles,
        [string[]] $ExcludeProperty,
        [switch] $NoAliasOrScriptProperties,
        [switch] $DisplayPropertySet
    )
    [int] $Run = 0
    $Array = New-ArrayList
    $Titles = New-ArrayList
    if ($NoAliasOrScriptProperties) {$PropertyType = 'AliasProperty', 'ScriptProperty'  } else {$PropertyType = ''}
    Write-Verbose "Format-PSTableConvertType2 - Option 2 - NoAliasOrScriptProperties: $NoAliasOrScriptProperties"

    foreach ($O in $Object) {
        $ArrayValues = New-ArrayList
        if ($DisplayPropertySet -and $O.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames) {
            $ObjectProperties = $O.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames.Where( { $ExcludeProperty -notcontains $_  } ) #.Name
        } else {
            $ObjectProperties = $O.PSObject.Properties.Where( { $PropertyType -notcontains $_.MemberType -and $ExcludeProperty -notcontains $_.Name  } ).Name
        }
        #$ObjectProperties = $O.PSObject.Properties
        foreach ($Name in $ObjectProperties) {
            if ($Run -eq 0 -and -not $SkipTitle) { Add-ToArray -List $Titles -Element $Name }
            Add-ToArray -List $ArrayValues -Element $O.$Name
        }
        if ($Run -eq 0 -and -not $SkipTitle) {Add-ToArray -List ($Array) -Element $Titles }
        Add-ToArray -List $Array -Element $ArrayValues
        $Run++
    }

    return , $Array
}
它本质上是将对象转换为数组数组。这使得只循环遍历行/列变得很简单


现在很重要的一点是,虽然通常我可以让Get AdUser以适当的顺序只显示我想要的值,但我正在处理通用模块(PSWriteWord/PSWriteExcel),我希望人们向它传递任何对象,而不必太在意它

除非有更好的选择:

$SpecialData = $Domain.DomainUsersFullList | Select-Object $($Domain.DomainUsersFullList[0]).PSObject.Properties.Name

$($Domain.DomainUsersFullList[0]).PSObject.Properties.Name[12]
$($Domain.DomainUsersFullList[10]).PSObject.Properties.Name[12]
$($SpecialData[0] | Select-Object $($Domain.DomainUsersFullList[0]).PSObject.Properties.Name).PSObject.Properties.Name[12]
$($SpecialData[10] | Select-Object $($Domain.DomainUsersFullList[0]).PSObject.Properties.Name).PSObject.Properties.Name[12]
基本上,这是复制第一个元素的顺序,并将相同的顺序应用于每一行。这确保了每个对象将按照与第一个元素相同的顺序返回属性

最后执行:

function Format-PSTableConvertType2 {
    [CmdletBinding()]
    param(
        $Object,
        [switch] $SkipTitles,
        [string[]] $ExcludeProperty,
        [switch] $NoAliasOrScriptProperties,
        [switch] $DisplayPropertySet,
        $OverwriteHeaders
    )
    #[int] $Run = 0
    $Array = New-ArrayList
    $Titles = New-ArrayList
    if ($NoAliasOrScriptProperties) {$PropertyType = 'AliasProperty', 'ScriptProperty'  } else {$PropertyType = ''}
    Write-Verbose "Format-PSTableConvertType2 - Option 2 - NoAliasOrScriptProperties: $NoAliasOrScriptProperties"

    # Get Titles first (to make sure order is correct for all rows)
    if ($OverwriteHeaders) {
        $Titles = $OverwriteHeaders
    } else {
        foreach ($O in $Object) {
            if ($DisplayPropertySet -and $O.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames) {
                $ObjectProperties = $O.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames.Where( { $ExcludeProperty -notcontains $_  } ) #.Name
            } else {
                $ObjectProperties = $O.PSObject.Properties.Where( { $PropertyType -notcontains $_.MemberType -and $ExcludeProperty -notcontains $_.Name  } ).Name
            }
            foreach ($Name in $ObjectProperties) {
                Add-ToArray -List $Titles -Element $Name
            }
            break
        }
        # Add Titles to Array (if not -SkipTitles)
        if (-not $SkipTitle) {
            Add-ToArray -List $Array -Element $Titles
        }
    }
    # Extract data (based on Title)
    foreach ($O in $Object) {
        $ArrayValues = New-ArrayList
        foreach ($Name in $Titles) {
            Add-ToArray -List $ArrayValues -Element $O.$Name
        }
        Add-ToArray -List $Array -Element $ArrayValues
    }
    return , $Array
}

物业的“适当”顺序是什么?我想这取决于你想做什么。你的总体目标是什么?也许有一个更简单/更好的方法来实现它-目前,这听起来像一个好问题,我得到的问题是,如果你问第一个对象,顺序将不同于最后一个。如果你试着把它放到Word或Excel中,会确保标题会乱七八糟。我希望第1个和第12个对象的顺序是一致的。为什么顺序在第一位很重要?您应该按名称而不是索引访问属性。如果要在Word或Excel中使用导出的用户数据:将数据导出为CSV。我要做的是获取$Domain>DomainUsersFullList,然后循环遍历它。逐一地。因为我不需要对象,所以我用PSObject.properties.Name扫描所有可用的属性。然后我开始把它放到excel/word上。$Domain.DomainUsesFullList中的每一个下一个对象都将经过该。。但在较大的对象(100列)上,我得到了不同的属性顺序,这意味着我创建的标题不再好了。我可能可以通过保存第一个属性顺序并将该属性顺序应用于下一个对象来解决这个问题,但我认为可能有更好的方法。我不想使用CSV。我编写了powershell模块,它可以将任何对象转换为Excel工作表,直接将数据导出到Excel。添加csv没有多大意义,对吗?