Powershell - 在 for 循环中使用 invoke-command
Powershell - Using invoke-command in a for loop
当我尝试 运行 为 Active-Directory 中的每台计算机调用命令时,我会遇到以下错误:
“调用命令:一个或多个计算机名称无效。如果您尝试传递 URI,请使用 -ConnectionUri 参数,或传递 URI 对象而不是字符串。”
```
$Hosts_Array=Get-ADComputer -Properties CN -Filter * | Sort-Object | Select-Object CN
foreach ($i in $Hosts_Array) {
Invoke-Command -ComputerName $i -ScriptBlock { Get-Service -Name "sysmon64"}
}
```
我使用 For 循环 运行 从 AD 获取的每台计算机的命令。
如果将 invoke-command 放入 try/catch 块会怎样?
$Hosts_Array=Get-ADComputer -Properties CN -Filter * | Sort-Object | Select-Object CN
foreach ($i in $Hosts_Array) {
try{
Invoke-Command -ComputerName $i -ScriptBlock { Get-Service -Name "sysmon64"}
}
catch{
write-output("Unable to resolve $i ")
}
}
如评论所述,Select-Object
returns 个对象,在本例中对象只有一个 属性,名为 'CN'。
事实上,您根本不需要请求 CN,因为 Get-ADComputer
returns 默认情况下这些属性:
DistinguishedName, DNSHostName, Enabled, Name, ObjectClass, ObjectGUID, SamAccountName, SID, UserPrincipalName
您可以通过以下方式简化代码:
$Hosts_Array = (Get-ADComputer -Filter *).Name | Sort-Object
foreach ($computer in $Hosts_Array) {
Invoke-Command -ComputerName $computer -ScriptBlock { Get-Service -Name "sysmon64" }
}
(Get-ADComputer -Filter *).Name
returns 仅包含计算机名称的 字符串 数组,也可以使用 Get-ADComputer -Filter * | Select-Object -ExpandProperty Name
来完成
P.S。我已将变量名更改为从 $i
(通常在编号循环中使用)迭代到 $computer
以使其更清晰
AD 中的每个对象都有一个 Relative Distinguished Name
(RDN)。这是对象在其父对象中的名称 OU/Container。对于用户、组、计算机和容器对象,RDN 是 cn
属性(通用名称)的值。对于 OU 对象,RDN 是 ou
属性的值。对于域组件对象,它是 dc
属性。
Name
属性 returns 任何对象的 RDN。
我不会使用 invoke-command
,因为 Get-Service
可用于远程连接到计算机。
如果您更喜欢使用get-service
,那么您可以尝试以下脚本:
$Hosts_Array = Get-ADComputer -Properties * -Filter *
$Obj = @()
$ServiceName = "sysmon64"
foreach ($Computer in $Hosts_Array)
{
$Hostname = $computer.name
# Check if computer is online
write-host "pinging $Hostname" -for Cyan
$ping = Test-Connection $Hostname -Count 1 -Quiet
if ($ping)
{
write-host "Computer found - $Hostname" -ForegroundColor Green
$Service = $null
$Service = Get-Service $ServiceName -ComputerName $Hostname -ErrorAction SilentlyContinue
if ($ServiceName)
{
write-host "Service $ServiceName found - $Hostname" -ForegroundColor Green
# create a hash table to store the date
$Hash = @{
Hostname = $Hostname
ServiceName = $Service.Name
Displayname = $Service.DisplayName
Status = $Service.Status
}
$Obj += New-Object psobject -Property $hash
}
else
{
write-host "Service NOT $ServiceName found - $Hostname" -ForegroundColor red
}
}
else
{
write-host "Computer found - $Hostname" -for Red
}
}
$Obj
这可能是最常见的 powershell 问题。使用 foreach 或 select -expand 或 .CN 将 CN 属性 取消引用到字符串中,它将起作用。我会 运行 一次整个列表,所以它 运行 是并行的。
$hosts_array = Get-ADComputer -Properties CN -Filter * | Sort-Object |
foreach-object CN
invoke-command $hosts_array { get-service sysmon64 }
当我尝试 运行 为 Active-Directory 中的每台计算机调用命令时,我会遇到以下错误: “调用命令:一个或多个计算机名称无效。如果您尝试传递 URI,请使用 -ConnectionUri 参数,或传递 URI 对象而不是字符串。”
```
$Hosts_Array=Get-ADComputer -Properties CN -Filter * | Sort-Object | Select-Object CN
foreach ($i in $Hosts_Array) {
Invoke-Command -ComputerName $i -ScriptBlock { Get-Service -Name "sysmon64"}
}
```
我使用 For 循环 运行 从 AD 获取的每台计算机的命令。
如果将 invoke-command 放入 try/catch 块会怎样?
$Hosts_Array=Get-ADComputer -Properties CN -Filter * | Sort-Object | Select-Object CN
foreach ($i in $Hosts_Array) {
try{
Invoke-Command -ComputerName $i -ScriptBlock { Get-Service -Name "sysmon64"}
}
catch{
write-output("Unable to resolve $i ")
}
}
如评论所述,Select-Object
returns 个对象,在本例中对象只有一个 属性,名为 'CN'。
事实上,您根本不需要请求 CN,因为 Get-ADComputer
returns 默认情况下这些属性:
DistinguishedName, DNSHostName, Enabled, Name, ObjectClass, ObjectGUID, SamAccountName, SID, UserPrincipalName
您可以通过以下方式简化代码:
$Hosts_Array = (Get-ADComputer -Filter *).Name | Sort-Object
foreach ($computer in $Hosts_Array) {
Invoke-Command -ComputerName $computer -ScriptBlock { Get-Service -Name "sysmon64" }
}
(Get-ADComputer -Filter *).Name
returns 仅包含计算机名称的 字符串 数组,也可以使用 Get-ADComputer -Filter * | Select-Object -ExpandProperty Name
P.S。我已将变量名更改为从 $i
(通常在编号循环中使用)迭代到 $computer
以使其更清晰
AD 中的每个对象都有一个 Relative Distinguished Name
(RDN)。这是对象在其父对象中的名称 OU/Container。对于用户、组、计算机和容器对象,RDN 是 cn
属性(通用名称)的值。对于 OU 对象,RDN 是 ou
属性的值。对于域组件对象,它是 dc
属性。
Name
属性 returns 任何对象的 RDN。
我不会使用 invoke-command
,因为 Get-Service
可用于远程连接到计算机。
如果您更喜欢使用get-service
,那么您可以尝试以下脚本:
$Hosts_Array = Get-ADComputer -Properties * -Filter *
$Obj = @()
$ServiceName = "sysmon64"
foreach ($Computer in $Hosts_Array)
{
$Hostname = $computer.name
# Check if computer is online
write-host "pinging $Hostname" -for Cyan
$ping = Test-Connection $Hostname -Count 1 -Quiet
if ($ping)
{
write-host "Computer found - $Hostname" -ForegroundColor Green
$Service = $null
$Service = Get-Service $ServiceName -ComputerName $Hostname -ErrorAction SilentlyContinue
if ($ServiceName)
{
write-host "Service $ServiceName found - $Hostname" -ForegroundColor Green
# create a hash table to store the date
$Hash = @{
Hostname = $Hostname
ServiceName = $Service.Name
Displayname = $Service.DisplayName
Status = $Service.Status
}
$Obj += New-Object psobject -Property $hash
}
else
{
write-host "Service NOT $ServiceName found - $Hostname" -ForegroundColor red
}
}
else
{
write-host "Computer found - $Hostname" -for Red
}
}
$Obj
这可能是最常见的 powershell 问题。使用 foreach 或 select -expand 或 .CN 将 CN 属性 取消引用到字符串中,它将起作用。我会 运行 一次整个列表,所以它 运行 是并行的。
$hosts_array = Get-ADComputer -Properties CN -Filter * | Sort-Object |
foreach-object CN
invoke-command $hosts_array { get-service sysmon64 }