簡體   English   中英

在PowerShell中動態向數組添加元素

[英]Dynamically an add element to an array in PowerShell

我正在嘗試對AD運行查詢以提供用戶列表。 由於我們的組織將標記“ LastName,FirstName”添加到計算機對象的描述字段中,因此我也想列出每個用戶分配的計算機。 這是我到目前為止的內容:

$ADGroup = "SomeADGroup"
$UserList = Get-ADGroupMember -Identity $ADGroup -Recursive `
  | Select SamAccountName `
  | foreach-object {(Get-ADUser -Identity $_.SamAccountName `
  | Select @{n='AssignedUser';e={$_.Surname + ", " + $_.GivenName}}).AssignedUser}


$Results = New-Object System.Collections.Generic.List[System.Object]

foreach ($User in $UserList)
{
    $MachineList = @(((Get-ADComputer -Filter "Description -like `"*$User*`"" | Select Name).Name) -join $_ + ",").ToUpper()

    foreach ($Machine in $MachineList)
    {
        $Results +=
            @{
                'User' = $User
                'Machine' = $Machine
            }
    }
}

$Results | ForEach-Object { [pscustomobject] $_ } | Format-Table

結果是這樣的:

User                 Machine
----                 -------

White, Scott         W107175
Jones, Henry         W107195
Flinstone, Fred      L109531,W108812

由於可以為每位用戶分配多台計算機,因此我試圖找到一種向陣列動態添加“列”的方法,以便每個計算機名稱元素都位於列中。 最終,這將使導出到CSV更加容易。 我正在尋找類似於以下內容的輸出:

User                 Machine   Machine2
----                 -------   -------

White, Scott         W107175
Jones, Henry         W107195
Flinstone, Fred      L109531   W108812

好的,因此您想向現有對象添加未知數量的屬性。 使用Add-Member cmdlet並不難做到。 接下來,您只需要構造一個循環,以便添加這些屬性容易理解,我們可以使用For循環來完成。 最后,您需要確保數組中的第一條記錄具有所有可能的屬性。 當我們到達那里時,我會再說明一點。

首先,我們獲得用戶。 我更改了您的內容,因為我嚴格反對將反引號用作換行符,因為反引號很容易被空白挫敗。 我還將$UserList從字符串數組更改$UserList對象數組,因為無論如何以后都需要對象。 我們仍然捕獲名字和姓氏,但是作為[PSCustomObject]上的User屬性。

$ADGroup = "SomeADGroup"
$UserList = Get-ADGroupMember -Identity $ADGroup -Recursive |
    Select SamAccountName |
    foreach-object {
        Get-ADUser -Identity $_.SamAccountName | 
            Select @{n='User';e={$_.Surname + ", " + $_.GivenName}}
    }

因此,現在我們有了具有一個屬性的對象數組。 現在我們遍歷整個過程,搜索計算機,然后將計算機捕獲為字符串數組。 那只是您已經修改過的代碼。

foreach ($User in $UserList)
    {         
        $MachineList = Get-ADComputer -Filter {Description -like "*$($User.User)*"} | Select -ExpandProperty Name

現在是我們稍微改變一下的地方。 對於發現的每台機器,我們都需要向已經擁有的對象添加一個屬性。 因為我們不知道有多少個,所以我們可以使用For循環並對屬性進行相應編號。

        for($i=0;$i -le $MachineList.Count;$i++)
            {
                Add-Member -InputObject $User -NotePropertyName "Machine$($i+1)" -NotePropertyValue $MachineList[$i]
            }
    }

因此,現在$UserList是一個對象數組,每個對象都有User屬性,但是有許多適合該用戶的Machine#屬性。 問題是PowerShell會根據數組中的第一個對象輸出對象數組。 因此,在您的示例中:

User                 Machine   Machine2           
----                 -------   -------    
White, Scott         W107175           
Jones, Henry         W107195           
Flinstone, Fred      L109531   W108812

Machine2列將永遠不會顯示,因為該屬性在Scott White的第一條記錄中不存在。 因此,為了解決這個問題,我們需要找出數組中任何給定對象的所有可能的屬性,並將所有缺失的屬性添加到第一條記錄中。 使用PowerShell中每個對象都具有的隱藏PSObject屬性可以輕松完成此操作。

首先,我們獲得所有可能的屬性名稱的列表:

$AllProps = $UserList | ForEach{$_.PSObject.Properties.Name} | Select -Unique

然后,我們過濾掉第一個記錄上已經存在的所有屬性,然后再次使用Add-Member cmdlet將剩下的所有內容作為新屬性添加到記錄中。

$AllProps | 
    Where{ $_ -notin $UserList[0].psobject.properties.name } | 
    ForEach{ Add-Member -InputObject $UserList[0] -NotePropertyName $_ -NotePropertyValue $null }

然后,除了輸出結果之外,別無所要做,因為自從我們創建了用戶列表以來,結果已經存儲在$UserList ,並且只需使用每個用戶的計算機更新該現有列表,而不是創建用戶列表,然后再創建一個新的列表。用戶加機器。

$UserList |  Format-Table

您已經很了解“變量”問題了; 根本上你永遠不會寫

$User.Machine1
$User.Machine2
$User.Machine...

因為您不知道有多少台計算機,所以無法在代碼中寫入屬性名稱。 數組就是解決這個問題的方法,並且您的代碼中有一個變量引用了一個數組,其中包含所有機器。 然后,您的代碼就變得有意義,簡單,明智且有效,但是它與您的CSV夢想不符-因為您的數據不是CSV形的。

如果為每位用戶向每台計算機添加一個屬性,則某些用戶擁有一台計算機,而某些用戶則具有四台...,這會激起Format-TableConvertTo-CsvOut-GridView ,因為他們采用了第一個對象他們將其視為模板,然后刪除不在第一個對象上的其他對象上的任何列。

因此,您必須執行TheMadTechnician的操作,然后回去向所有對象動態添加所有空白的MachineN屬性,並且如果您只是說“將有N列”,這將非常簡單。

然后,您可以對它們進行計數,而我得到了:

$ADGroup = "SomeADGroup"
$ColumnCount = 10

Get-ADGroupMember -Identity $ADGroup -Recursive | Get-ADUser | ForEach-Object {

    $User = [ordered]@{ 'User' = $_.SurName + ", " + $_.GivenName }

    $Machines = @((Get-ADComputer -Filter "Description -like '*$($User.User)*'").Name)

    for ($i=0; $i -lt $ColumnCount; $i++)
    {
        $User["Machine$i"] = $Machines[$i]
    }

    [PSCustomObject]$User

} | ConvertTo-Csv

NB。 我依賴數組的超出范圍的行為。 如果需要避免這種情況,請在“計算機”列表的末尾添加10列空字符串作為緩沖區。

但是我仍然很想自己使用字符串操作混搭CSV格式,並且根本不遍歷對象,因為您不使用它們,因為它們“應該”被使用,而只是走了很長一段路制作正確的屬性只是為了扔掉它們以獲得CSV。


偏離主題,您的代碼非常復雜:

$UserList = Get-ADGroupMember -Identity $ADGroup -Recursive `
| Select SamAccountName `
| foreach-object {(Get-ADUser -Identity $_.SamAccountName `
| Select @{n='AssignedUser';e={$_.SurName + ", " + $_.GivenName}}).AssignedUser}

獲得AD組成員,然后以完全不執行任何操作的方式選擇SamAccountName,然后遍歷結果,而不是直接將其直接傳遞到Get-ADUser,這毫無用處,然后選擇一個計算所得的屬性,然后將其拋出離開並獲得價值。 代替:

Get-ADGroupMember -Identity $ADGroup -Recursive | Get-ADUser | ForEach-Object { $_.SurName + ', ' + $_.GivenName }

獲取組成員,獲取其AD用戶,然后根據這些結果計算您的字符串。

$Results = New-Object System.Collections.Generic.List[System.Object]
->
$Results = @()

或者,更好的是:

$Results = @()
foreach ($x in $y) {
    $Results += ...
}

->

$Results = foreach ($x in y ) {
    ...
}

和在

| ForEach-Object { [pscustomobject] $_ } |

您...在制作它們時可以使它們成為PSCustomObject ,然后就不需要了。

$ADGroup = "Some AD Group"
$UserList = Get-ADGroupMember -Identity $ADGroup -Recursive | Get-ADUser

$Results = @()
$MaxMachineCount = 0

foreach ($User in $UserList)
{
    if ($User.SurName -and $User.GivenName -ne $null)
    {
        $CurrentUser = [ordered]@{ 'User' = $User.SurName + ", " + $User.GivenName }
        $MachineList = @(((Get-ADComputer -Filter "Description -like `"*$($CurrentUser.User)*`"") | Select -ExpandProperty Name))

        for ($i=0; $i -lt $MachineList.Count; $i++)
        {
            $CurrentUser.Add("Machine $i","$($MachineList[$i].ToUpper())")
            if ($MaxMachineCount -le $i) {$MaxMachineCount++}
        }
        $Results += [PSCustomObject]$CurrentUser
    }
}

for ($i=0; $i -lt $MaxMachineCount; $i++){$Results[0] | Add-Member -Name "Machine $i" -Value $null -MemberType NoteProperty -ErrorAction Ignore}

$Results | Format-Table -AutoSize

最后的代碼Format-Table -AutoSize也可以替代ConvertTo-CSV | Out-File "C:\\Some\\Directory\\File.csv" ConvertTo-CSV | Out-File "C:\\Some\\Directory\\File.csv"

我添加了它以在結果中創建其他列。 以前,每個用戶最多只能顯示兩台計算機。 現在,該腳本將為每個用戶返回所有分配的計算機。

for ($i=0; $i -lt $MachineList.Count; $i++){$Results[0] | Add-Member -Name "Machine $i" -Value $null -MemberType NoteProperty -ErrorAction Ignore

這是我的結果:

User                Machine 0 Machine 1 Machine 2 Machine 3 Machine 4 Machine 5 Machine 6 Machine 7 Machine 8
----                --------- --------- --------- --------- --------- --------- --------- --------- ---------
Froeman, Abe        L110911
Maclatchie, Matthew W109370   L108518
White, Walter       V999100   L107800   V999109   V999108   V999107   V999102   V999106   V999105   V999101

感謝@TessellatingHeckler和@TheMadTechnician的輸入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM