PowerShell作业获取AD中PC序列号时Shell崩溃的排查与处理
解决PowerShell获取AD电脑序列号时Shell崩溃问题
一、临时绕过异常电脑
直接在AD电脑列表中排除这台问题机器,避免触发崩溃:
# 从AD获取所有电脑并过滤异常机器 $allADComputers = Get-ADComputer -Filter * | Select-Object -ExpandProperty Name $validComputers = $allADComputers | Where-Object { $_ -ne "proektor-bnu" } # 使用过滤后的列表执行作业 $arrayJobs = Get-WmiObject -ComputerName $validComputers -Class Win32_BIOS -AsJob -ErrorAction SilentlyContinue Wait-Job $arrayJobs $arrayJobs | Receive-Job | Format-Table PsComputerName, SerialNumber -AutoSize
二、捕获问题根源的方法
1. 改用更稳定的CIM命令替代WMI
CIM比WMI的错误处理更可靠,单独测试这台机器:
try { $ErrorActionPreference = "Stop" $result = Invoke-CimCommand -ComputerName "proektor-bnu" -ScriptBlock { Get-CimInstance -ClassName Win32_BIOS } -ErrorVariable cimError $result | Format-Table PsComputerName, SerialNumber -AutoSize } catch { Write-Host "访问proektor-bnu出错:" $cimError | Format-List * }
如果仍崩溃,说明该机器的CIM/WMI栈存在严重异常(比如WMI存储库损坏、系统文件损坏)。
2. 逐步排查基础连通性
先确认机器的网络和服务状态,避免Shell直接崩溃:
# 测试Ping连通性 if (Test-Connection -ComputerName "proektor-bnu" -Count 1 -Quiet) { Write-Host "机器可Ping通" # 测试WMI服务端口(135) $portTest = Test-NetConnection -ComputerName "proektor-bnu" -Port 135 if ($portTest.TcpTestSucceeded) { Write-Host "WMI端口开放" # 尝试极简WMI查询 try { Get-WmiObject -ComputerName "proektor-bnu" -Class Win32_ComputerSystem -ErrorAction Stop | Select-Object Name } catch { Write-Host "WMI查询失败:$_" } } else { Write-Host "WMI端口未开放" } } else { Write-Host "机器无法Ping通" }
通过逐步排查可以定位是网络问题还是服务本身的故障。
3. 启用PowerShell崩溃日志
若Shell仍崩溃,可生成崩溃转储文件用于分析:
- 打开注册表编辑器,定位到
HKLM:\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\powershell.exe - 若该路径不存在,手动创建此键值
- 添加以下DWORD值:
DumpType:设置为2(全内存转储)DumpFolder:指定日志存储路径(如C:\PSCrashDumps)
- 重新运行测试脚本,崩溃后会在指定路径生成转储文件,可使用WinDbg等工具分析崩溃原因。
三、批量处理时的容错优化
批量处理时改用循环逐个执行,避免单台机器故障导致整个Shell崩溃:
$allADComputers = Get-ADComputer -Filter * | Select-Object -ExpandProperty Name $results = @() foreach ($pc in $allADComputers) { Write-Host "正在处理:$pc" try { $ErrorActionPreference = "Stop" $biosInfo = Get-WmiObject -ComputerName $pc -Class Win32_BIOS $results += [PSCustomObject]@{ PsComputerName = $pc SerialNumber = $biosInfo.SerialNumber } } catch { Write-Host "处理$pc失败:$_" # 可选:将错误记录到日志文件 "$(Get-Date): $pc - $_" | Out-File -Append -Path "C:\ADSerialErrors.log" } } $results | Format-Table PsComputerName, SerialNumber -AutoSize
内容的提问来源于stack exchange,提问作者Ruslannnn
相关产品推荐
相关产品推荐

