PowerShell批量检查网络共享打印机权限运行缓慢优化求助
优化思路
- 替换串行遍历为
Invoke-Command并行执行,默认支持32台设备同时查询,可通过ThrottleLimit参数调整并发数,相比单线程遍历效率提升数十倍 - 新增预检查逻辑:先验证目标主机连通性/假脱机服务状态,不可达的主机直接跳过,避免无意义的超时等待
- 把打印机过滤、权限校验逻辑全部下沉到远程主机执行,仅回传符合风险条件的结果,大幅降低网络传输开销
- 移除低效的数组累加操作,直接接收远程命令返回的结果集,同时修复原代码变量名混用、单台报错终止全量扫描的问题
优化后代码示例
# 1. 筛选目标AD计算机 $excludeList = @("替换为你要排除的设备名列表") $ADComputer = Get-ADComputer -Filter 'Name -like "DC-*"' | Where-Object { $excludeList -notcontains $_.Name } $computerNames = $ADComputer.Name $ErrorCount = 0 # 可选:预检查主机在线状态,提前过滤离线设备,减少无效请求 $onlineComputers = $computerNames | Where-Object { Test-Connection $_ -Count 1 -Quiet -ErrorAction SilentlyContinue } # 2. 并行拉取并校验打印机权限 $riskPrinters = Invoke-Command -ComputerName $onlineComputers -ThrottleLimit 50 -ErrorAction SilentlyContinue -ScriptBlock { try { $printers = Get-Printer -Full -ErrorAction Stop foreach ($printer in $printers) { # 过滤非共享、PDF/XPS/OneNote等不需要的设备,可自行调整过滤规则 if (-not $printer.Shared -or $printer.Name -match "PDF|XPS|OneNote") { continue } # 直接用.NET内置类解析SDDL,无需额外引入Convert-SDDLToACL函数 $permissions = ([System.Security.AccessControl.RawSecurityDescriptor]$printer.PermissionSDDL).DiscretionaryAcl | ForEach-Object { $_.SecurityIdentifier.Translate([System.Security.Principal.NTAccount]).Value } if ("Everyone" -in $permissions) { # 仅返回风险结果,减少网络传输量 return [PSCustomObject]@{ ComputerName = $env:COMPUTERNAME PrinterName = $printer.Name } } } } catch { Write-Warning "主机 $($env:COMPUTERNAME) 假脱机服务不可用" return $null } } # 3. 结果统计与输出 $riskPrinters | ForEach-Object { Write-Warning "$($_.ComputerName) - $($_.PrinterName) - 存在Everyone权限风险!" $ErrorCount++ } Write-Host "扫描完成,共发现 $ErrorCount 台存在风险的共享打印机"
注意事项
Invoke-Command依赖目标主机开启WinRM服务,域环境可通过组策略批量开启,无额外配置成本- 并发数
ThrottleLimit可根据域控性能、网络带宽调整,常规千兆网络环境下设置为50-100都可以稳定运行 - 若存在部分主机无法开启WinRM的场景,可单独为这部分主机保留原
Get-Printer逻辑作为兜底
内容的提问来源于stack exchange,提问作者pyte
相关产品推荐
相关产品推荐

