将列表输入传递给 Get-ADComputer

将列表输入传递给 Get-ADComputer

因此,我编写了一个脚本,用于从 AD 获取有关用户及其关联计算机的一些信息。我在网上读到了一些人们在使用 Get-ADComputer cmdlet 时遇到的问题以及一些可能存在的错误。起初我以为这就是我在这里遇到的问题,但现在我不太确定了。

我的问题是我的代码运行正常,但如果我添加一段不相关的代码来从变量中获取一些信息,它就会破坏其他东西。看一看。

全部代码:http://paste.ofcode.org/Hgbiukp2XYqKnv2sdUGBKb

有问题的代码段:

## 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)}}
}

所以这部分工作得很好。现在,如果你添加一个获取有关用户名的信息的代码片段,你会看到它停止显示有关 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)}}
}

有人能告诉我这是为什么吗?以及如何解决它?

通常我只要玩玩就能搞清楚,但这个真的让我很困惑。我认为问题肯定出在变量的格式上$ComputerList,但列表中的每个项目都是字符串,这是必需的Get-ADComputer。所以我不知道。

谢谢大家。

答案1

我相信您的问题在于您将多种不同类型的对象写入输出管道(隐式地不将它们分配给变量)并依靠默认的 Powershell 格式规则将它们正确显示到控制台(但做不到)。

它显示第一种类型的对象,然后尝试使用与第一种相同的格式化程序显示第二种类型的对象,并且只写空行。如果您将 Get-ADUser 调用移到 Get-ADComputer 调用循环下方,则会遇到相反的问题。

假设此脚本的输出仅打算显示在控制台上,而不会由其他脚本进一步处理或与其他 cmdlet 链接,您可能希望Write-Host对输出的每个部分使用明确的格式。 但通常情况下,这不是一个好主意. 类似这样。

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

我还想就您的脚本的总体结构提供一些额外的建议。

首先,我会将你的$username变量设为强制参数,而不是显式调用Read-Host。如果命令行上尚未指定,Powershell 将自动提示它。

当您检查用户是否存在时,您正在将变量的对象类型$username从字符串更改为对象ADUser。我猜这不是您的意图,只是幸运的是,稍后对它的引用使用对象而不是字符串。您还可以Get-ADUser在此之后立即进行第二次调用以获取您关心的属性,这需要额外往返域控制器。我只是将两者结合起来并将您的## Get Username info部分移到 try/catch 块中。如果用户不存在,它仍会抛出相同的异常。我还将输出分配给一个新变量,例如$user

或者,您也可以跳过所有异常处理并更改调用Get-ADUser以使用-Filter {SamAccountName -eq $username}参数,然后像稍后使用一样测试 $null Get-ADComputer

您最终还会重复调用 Get-ADComputer。首先,您使用过滤器进行调用,然后对每个结果重新调用。将属性添加DNSHostName,LastLogonTimestamp到初始调用,然后直接迭代结果对象,而无需重新调用 Get-ADComputer,这样会更有效率。

最终的脚本可能如下所示:

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
}

相关内容