Arrays Powershell e comparações

3

Im um administrador de sistemas Linux por profissão, mas estou tendo que fazer alguns powershelling. Meu problema é este:

Estou recebendo uma lista de usuários ativos do AD com este comando:

$allusers= get-aduser -Filter {Enabled -eq $true} | FT samAccountName 

Minha intenção é que $ allusers se torne uma matriz preenchida com as linhas de saída do comando get-aduser. estourar este bloco logo após o array ser preenchido parece confirmar que é realmente o caso.

for ($i; $i -le $allusers.length; $i++) {
    $allusers[$i]
}

Ótimo! então agora eu quero verificar se um determinado nome de usuário existe dentro desse array. Vejo que os arrays incluem uma função "Contains ()" muito útil, que parece servir ao meu propósito.

echo $allusers.Contains("joeq")

Mas ai de mim! Eu recebo este erro:

Method invocation failed because [System.Object[]] doesn't contain a method named 'contains'.

Em C: \ Users \ dylanh \ jirauserpurge.ps1: 33 caracteres: 24 + echo $ allusers.contains < < < < ("joeq")     + CategoryInfo: InvalidOperation: (contains: String) [], RuntimeException     + FullyQualifiedErrorId: MethodNotFound

Hmmm ... OK, vamos lá "old skool"

for ($i; $i -le $allusers.length; $i++) {
    if ($allusers[$i] -eq "joeq") {
        echo "joeq present"
    }
}

A condição nunca é correspondida! Meu cérebro dói! OK, é possível que haja alguns caracteres de espaço em branco causando danos aqui, vamos aparar:

for ($i; $i -le $allusers.length; $i++) {
    if ($allusers[$i].Trim() -eq "joeq") {
        echo "joeq present"
    }
}

Mas não, isso resulta nisso:

Method invocation failed because [Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData] doesn't contain a method named 'Trim'.
At C:\Users\dylanh\jirauserpurge.ps1:39 char:24
+     if ($allusers[$i].Trim <<<< () -eq "nickf") {
+ CategoryInfo          : InvalidOperation: (Trim:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound

É evidente que é algum tipo de problema de transmissão de tipos que estou perdendo. O que preciso fazer para permitir pesquisar o "array" por um valor específico?

ATUALIZAÇÃO: Com a ajuda da resposta da fdibot e do comentário do HopelessN00b, tenho uma solução funcional:

$allusers= get-aduser -Filter {Enabled -eq $true}
$usernames = @()
for ($i=0; $i -le $allusers.length; $i++) {
    $usernames += $allusers[$i].SamAccountName
}
$usernames -contains "joeq"

O laço adicional parece um pouco redundante TBH (ou pelo menos seria em bash!) Ah bem! obrigado pela sua contribuição a todos.

    
por GeoSword 23.10.2014 / 10:11

4 respostas

8

O problema vem com sua Format-Table:)

$allusers= get-aduser -Filter {Enabled -eq $true} | FT samAccountName
$allusers |  gm

TypeName : Microsoft.PowerShell.Commands.Internal.Format.FormatStartData

Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode
Method int GetHashCode() GetType
Method type GetType() ToString
Method string ToString() autosizeInfo
Property Microsoft.PowerShell.Commands.Internal.Format.AutosizeInfo, Syste... ClassId2e4f51ef21dd47e99d3c952918aff9cd Property string ClassId2e4f51ef21dd47e99d3c952918aff9cd {get;} groupingEntry
Property
Microsoft.PowerShell.Commands.Internal.Format.GroupingEntry, Syst... pageFooterEntry Property
Microsoft.PowerShell.Commands.Internal.Format.PageFooterEntry, Sy... pageHeaderEntry Property
Microsoft.PowerShell.Commands.Internal.Format.PageHeaderEntry, Sy... shapeInfo Property
Microsoft.PowerShell.Commands.Internal.Format.ShapeInfo, System.M...

Não é isso que você deseja procurar por um nome de usuário.

Se você fizer isso

$allusers= get-aduser -Filter {Enabled -eq $true}
$allusers | gm

Você receberá uma coleção de objetos com todas as suas propriedades. E aqui você pode verificar com um if like that

$allusers.SamAccountName -eq "joeq"

Agora você pode continuar seu script e fazer um loop com todos os usuários, tente isto:

get-aduser -Filter {Enabled -eq $true} | Foreach {
  if ($_.SamAccountName -eq "something") { "OK" }
}
    
por 23.10.2014 / 11:14
3

Você pode usar "select -expand xxx" para produzir uma matriz achatada (?) onde você não precisa usar o nome da propriedade para analisar a matriz.

$allusers = get-aduser -Filter {Enabled -eq $true} | select -expand samAccountName
PS C:\> $allusers.contains("GeoSword")
True
    
por 23.10.2014 / 15:44
2

Se você não precisa usar $allusers como uma coleção de objetos de usuário várias vezes (ou se tudo que você precisa é dos nomes dos usuários), você pode reduzir o que está armazenando na memória do shell fazendo isso:

$usernames = (get-aduser -Filter {Enabled -eq $true}).samAccountName
$usernames.Contains("check_value")

Ou diga que você tinha uma matriz inteira de valores de verificação para os quais desejava dar um loop com o nome $check_array e queria verificar cada nome de usuário para ver se eles estavam nessa matriz:

$usernames = (get-aduser -Filter {Enabled -eq $true}).samAccountName
foreach ($i in $check_array) {
    $usernames.Contains($i)
}

Embora, dependendo dos comprimentos relativos dos dois arrays, esse segundo seja melhor:

foreach ($j in (get-aduser -Filter {Enabled -eq $true}).samAccountName) {
    $check_array.Contains($j)
}

Por fim, se você não precisar reutilizar a lista de nomes de usuários após essa etapa, precisará verificar apenas um valor de verificação:

((get-aduser -Filter {Enabled -eq $true}).samAccountName).Contains("check_value")

Retornará o resultado booleano desse cheque.

Esse último método, no entanto, não é exatamente o de melhores práticas se você estiver escrevendo um script ou uma função que alguém possa precisar desmontar para consertar ou reutilizar na sua ausência. Se é apenas para você e tudo que você precisa é que um resultado booleano, no entanto, eu iria com esse, ele deveria rodar aproximadamente a mesma quantidade de tempo, e você não estará se apegando a essa (potencialmente) enorme matriz de nomes de usuários (ou ainda maior variedade de objetos E a matriz de nomes de usuários). Novamente, porém, se você estiver reutilizando essa matriz de objetos de usuário, seu caminho deve ficar bem.

    
por 23.10.2014 / 20:20
1

A contagem da matriz com ($i=0; $i ... pode ser muito mais nítida - o PowerShell percorre as coisas muito bem com foreach , mas muitas vezes você também não precisa disso. Seu código final:

$allusers= get-aduser -Filter {Enabled -eq $true}
$usernames = @()
for ($i=0; $i -le $allusers.length; $i++) {
    $usernames += $allusers[$i].SamAccountName
}
$usernames -contains "joeq"

poderia ser:

$usernames = Get-ADUser -Filter {Enabled -eq $true} | select -Expand sAmAccountName
$usernames -contains "joeq"

Em que o select está escolhendo a propriedade ou propriedades a serem mantidas, e o parâmetro expand nivela essa propriedade em uma string simples em vez de mantê-la como um par nome / valor.

[Isso vem com a mesma resposta que Craig620, mas estou respondendo contra a contagem por loop, então o caminho para a resposta é diferente].

    
por 23.10.2014 / 20:16