#powershell #loops #foreach #try-catch
#powershell #циклы #foreach #попробуйте-поймать
Вопрос:
У меня есть этот скрипт, который выполняет цикл foreach для каждого компьютера, и для каждого компьютера он выполняет цикл через каждый сетевой адаптер. В настоящее время блок Catch не запущен. Что я хочу сделать, это поймать ошибку (обычно потому, что get-wmi не может подключиться к компьютеру), что-то сделать (добавить некоторую информацию в PSCustomObject), но затем перейти к следующей итерации. Как мне поймать ошибку, но также продолжить цикл foreach?
param (
[Alias('Hostname')]
[string[]]$ComputerName = @('pc1','pc2'),
$OldDNSIP = '7.7.7.7',
$NewDNSIP = @('9.9.9.9','8.8.8.8')
)
$FailedArray = @()
$DHCPArray = @()
Foreach ($Computer in $ComputerName){
$NICList = Get-WmiObject Win32_NetworkAdapterConfiguration -computername $Computer | where{$_.IPEnabled -eq "TRUE"}
Foreach($NIC in $NICList){
If($NIC.DHCPEnabled -eq $false){
Try{
$DNSIPs = $NIC.DNSServerSearchOrder
if($DNSIPs -contains $OldDNSIP){
$NewDNS = $DNSIPs | foreach {$_ -replace $OldDNSIP,$NewDNSIP[0]}
$null = $NIC.SetDNSServerSearchOrder($NewDNS)
}
else{
write-host " - Old DNS server IP not found... ignoring"
}
}
Catch{
write-host " - Something went wrong... logging to a CSV for review later" -ForegroundColor Red
$FailedArray = [PSCustomObject]@{
'Computer' = $Nic.pscomputername
'NIC_ID' = $nic.index
'NIC_Descrption' = $nic.description}
}
}
ElseIf($NIC.DHCPEnabled -eq $true){
write-host " - DHCP is enabled. Adding this IP, Hostname, Nic Index and DHCP Server to a CSV for reviewing."
#add pscomputer, nic id, refernece and dhcp server to DHCPNICArray
$DHCPArray = [PSCustomObject]@{
'Computer' = $Nic.pscomputername
'NIC_ID' = $nic.index
'NIC_Descrption' = $nic.description
'DHCPEnabled' =$nic.dhcpenabled
'DHCPServer' = $nic.dhcpserver}
}
}
}
$DHCPArray | export-csv c:tempdhcp.csv -NoTypeInformation
$FailedArray | export-csv c:tempfailed.csv -NoTypeInformation
Ответ №1:
Если ошибки WMI вызваны сбоем соединения, они возникнут до того, как будут обработаны какие-либо сетевые адаптеры. Если вы хотите перехватить их, а затем продолжить на следующем компьютере, вам нужно переместить try-catch до уровня этого цикла. Если вы также хотите перехватить ошибки, относящиеся к сетевой карте, вам потребуется 2-я попытка-перехват на этом уровне.
Кроме того, рассмотрите возможность использования -ErrorAction Stop
параметра или указания $ErrorActionPreference = 'Stop'
, чтобы убедиться, что все ошибки завершаются (это означает, что переходите прямо к блоку catch).
Вот пример с комментариями для объяснения:
$ErrorActionPreference = 'Stop'
foreach ($Computer in $ComputerName) {
# add a try-catch per computer,
# to catch WMI errors
# and then continue with the next computer afterwards
try {
# if errors occur here,
# execution will jump right to the catch block the bottom
$NICList = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Computer -ErrorAction Stop | where {
$_.IPEnabled -eq "TRUE"
}
foreach ($NIC in $NICList) {
# add a try-catch per NIC,
# to catch errors with this specific NIC and then
# continue with the next nic
try {
if ($NIC.DHCPEnabled -eq $false){
$DNSIPs = $NIC.DNSServerSearchOrder
if ($DNSIPs -contains $OldDNSIP) {
$NewDNS = $DNSIPs | foreach {$_ -replace $OldDNSIP,$NewDNSIP[0]}
$null = $NIC.SetDNSServerSearchOrder($NewDNS)
}
else {
write-host " - Old DNS server IP not found... ignoring"
}
}
elseif ($NIC.DHCPEnabled -eq $true){
write-host " - DHCP is enabled. Adding this IP, Hostname, Nic Index and DHCP Server to a CSV for reviewing."
$DHCPArray = [PSCustomObject]@{
'Computer' = $Nic.pscomputername
'NIC_ID' = $nic.index
'NIC_Descrption' = $nic.description
'DHCPEnabled' =$nic.dhcpenabled
'DHCPServer' = $nic.dhcpserver
}
}
}
catch {
write-host " - Configuring a NIC went wrong... logging to a CSV for review later" -ForegroundColor Red
# add nic-specific entry
$FailedArray = [PSCustomObject]@{
'Computer' = $Nic.pscomputername
'NIC_ID' = $nic.index
'NIC_Descrption' = $nic.description
}
}
# continue with next nic...
} # foreach nic
}
catch {
write-host " - Something else went wrong... logging to a CSV for review later" -ForegroundColor Red
# add entry for current computer
# (we don't know about nics, because wmi failed)
$FailedArray = [PSCustomObject]@{
'Computer' = $Computer
}
}
# continue with next computer...
} # foreach computer
Комментарии:
1. Аааа, это имеет смысл! Теперь я понимаю, как и почему try / catch был в неправильном месте в скрипте. Большое спасибо, я попробую