Entrada de lista de passagem para Get-ADComputer

1

ASSIM Escrevi um script que obtém algumas informações do AD sobre um usuário e seu (s) computador (es) associado (s). Eu li on-line sobre alguns dos problemas que as pessoas enfrentam com o cmdlet Get-ADComputer e alguns bugs possíveis com ele. No começo eu pensei que era o que eu tinha encontrado aqui, mas agora eu não tenho tanta certeza.

Meu problema é que meu código funciona bem, mas se eu adicionar um snippet de código não relacionado para obter alguma informação de uma variável, ele quebra outra coisa. Dê uma olhada.

Código inteiro: link

O código em questão:

## Prompt host for input
$username = Read-Host -Prompt "Enter the Username"

## Get list of computers
$ComputerList = Get-ADComputer -Filter {ManagedBy -eq $username} -Properties ManagedBy | Select-Object -ExpandProperty Name

## Compute and format results
Foreach ($Computer in $ComputerList)
{
    $OnlineStatus = Test-Connection -ComputerName $Computer -BufferSize 16 -Count 1 -Quiet
    If ($OnlineStatus -like "True") {$OnlineStatus = "$True"} else {$OnlineStatus = "$False"}

    Get-ADComputer -Identity $Computer -Properties ManagedBy,DNSHostName,LastLogonTimestamp |
    Select-Object DNSHostName,@{Name="Active";Expression={$OnlineStatus}},@{Name="LastLogonTimestamp";Expression={[datetime]::FromFileTime($_.LastLogonTimestamp)}}
}

Então esta parte funciona perfeitamente. Agora, se você adicionar um snippet que obtenha algumas informações sobre o nome de usuário, poderá ver que ele pára de exibir a saída sobre o computador do AD.

## Prompt host for input
$username = Read-Host -Prompt "Enter the Username"

## Get Username info
Get-ADUser -Identity $username –Properties “DisplayName”, “msDS-UserPasswordExpiryTimeComputed”, "LockedOut" |
Select-Object -Property @{Name="Name";Expression={$_.DisplayName}},@{Name=“PWD Expiration Timestamp”;Expression={[datetime]::FromFileTime($_.“msDS-UserPasswordExpiryTimeComputed”)}},LockedOut

## Get list of computers
$ComputerList = Get-ADComputer -Filter {ManagedBy -eq $username} -Properties ManagedBy | Select-Object -ExpandProperty Name

## Compute and format results
Foreach ($Computer in $ComputerList)
{
    $OnlineStatus = Test-Connection -ComputerName $Computer -BufferSize 16 -Count 1 -Quiet
    If ($OnlineStatus -like "True") {$OnlineStatus = "$True"} else {$OnlineStatus = "$False"}

    Get-ADComputer -Identity $Computer -Properties ManagedBy,DNSHostName,LastLogonTimestamp |
    Select-Object DNSHostName,@{Name="Active";Expression={$OnlineStatus}},@{Name="LastLogonTimestamp";Expression={[datetime]::FromFileTime($_.LastLogonTimestamp)}}
}

Alguém pode me dizer por que isso é? E como consertar isso?

Normalmente sou capaz de descobrir apenas tocando com ele, mas este realmente me deixou perplexo. Eu acho que o problema deve ser com a formatação da variável $ComputerList , mas cada item na lista é uma String, que é o que requer Get-ADComputer . Então eu simplesmente não sei.

Obrigado a todos antecipadamente.

    
por Michael Timmerman 22.12.2016 / 00:31

1 resposta

1

Acredito que seu problema gira em torno do fato de que você está escrevendo vários tipos diferentes de objetos no pipeline de saída (implicitamente não atribuindo-os a uma variável) e confiando nas regras de formatação padrão do Powershell para exibi-las adequadamente no console ( o que não pode).

Ele está exibindo o primeiro tipo de objeto e, em seguida, tentando exibir o segundo tipo de objeto usando o mesmo formatador que o primeiro e apenas escrevendo linhas em branco. Você teria o problema oposto se mover sua chamada Get-ADUser abaixo do loop com as chamadas Get-ADComputer.

Supondo que a saída desse script tenha sempre a intenção de ser exibida no console e não ser processada posteriormente por outros scripts ou encadeada com outros cmdlets, convém usar Write-Host com formatação explícita para cada parte de sua saída. Normalmente, esta é uma má ideia embora . Algo parecido com isto.

$user = Get-ADUser -Identity $username –Properties “DisplayName”, “msDS-UserPasswordExpiryTimeComputed”, "LockedOut"
Write-Host "User: $($user.DisplayName)'tPWD Expiration: $([datetime]::FromFileTime($_.“msDS-UserPasswordExpiryTimeComputed”))'tLockedOut: $($user.LockedOut)"

Também gostaria de oferecer alguns conselhos adicionais sobre a estrutura geral do seu script.

Primeiro, eu tornaria sua variável $username um parâmetro obrigatório em vez de chamar explicitamente Read-Host . O Powershell solicitará automaticamente se não estiver especificado na linha de comando.

Ao verificar a existência do usere, você está alterando o tipo de objeto de sua variável $username de uma string para um objeto ADUser . Eu estou supondo que isso não foi sua intenção e é apenas uma sorte que as referências posteriores trabalhem usando o objeto em vez da string. Você também faz uma segunda chamada Get-ADUser logo depois para obter os atributos de seu interesse, o que custa uma ida e volta extra ao controlador de domínio. Eu apenas combinei os dois e movi sua seção ## Get Username info para o bloco try / catch. Ele ainda lançará a mesma exceção se o usuário não existir. Eu também atribuiria a saída a uma nova variável como $user .

Opcionalmente, você também pode ignorar todo o tratamento de exceções e alterar a chamada Get-ADUser para usar o parâmetro -Filter {SamAccountName -eq $username} e, em seguida, testar apenas para $ null, como acontece mais tarde com Get-ADComputer .

Você também acaba duplicando suas chamadas para Get-ADComputer. Primeiro você está chamando com o filtro e, em seguida, está chamando novamente cada resultado. Seria mais eficiente apenas adicionar os atributos DNSHostName,LastLogonTimestamp à chamada inicial e depois iterar diretamente sobre os objetos resultantes sem a necessidade de chamar novamente o Get-ADComputer.

Veja como um script resultante pode parecer:

param(
    [Parameter(Mandatory=$true,Position=0)]
    [string]$username
)

# Import AD Module
Import-Module ActiveDirectory

Write-Host "Active Domain: $((Get-ADDomain).DNSRoot)"

# Get user details
$user = Get-ADUser -Filter {SamAccountName -eq $username} -Properties DisplayName,msDS-UserPasswordExpiryTimeComputed,LockedOut
If ($user -eq $null) {
    Write-Error "Error: Username not found. Exiting"
    Exit
}
Write-Host "Name: $($user.DisplayName)"
Write-Host "PWD Expiration Timestamp: $([datetime]::FromFileTime($_.'msDS-UserPasswordExpiryTimeComputed'))"
Write-Host "LockedOut: $($user.LockedOut)"

# Get managed computers
$ComputerList = Get-ADComputer -Filter {ManagedBy -eq $username} -Properties ManagedBy,DNSHostName,LastLogonTimestamp

# Error-Handling: If no computers found
If ($ComputerList -eq $null) {
    Write-Error "No computers found"
    Exit
}

# Compute and format results
ForEach ($computer in $ComputerList) {

    $OnlineStatus = Test-Connection -ComputerName $computer.Name -BufferSize 16 -Count 1 -Quiet

    # since this is now the only type of object we will be putting on the pipeline,
    # it's ok to just do that now
    $computer | Select-Object DNSHostName,@{L="Active";E={$OnlineStatus}},@{L="LastLogonTimestamp";E={[datetime]::FromFileTime($_.LastLogonTimestamp)}} | Write-Output
}
    
por 22.12.2016 / 04:15