VB程序中System.Drawing.Printing.PrinterSettings.InstalledPrinters遍历操作挂起问题排查求助
排查VB应用遍历网络打印机时阻塞的问题
首先,结合你描述的情况——之前正常运行数千次,现在突然阻塞,且只有重启系统能恢复,说明问题大概率出在系统层面的打印机枚举逻辑或网络打印机状态异常,而非代码本身的逻辑错误。以下是具体的排查方向:
1. 先验证手动枚举打印机是否也会阻塞
直接去Windows控制面板的「设备和打印机」里刷新列表,或者用命令行执行wmic printer list brief:
- 如果手动操作也卡住,那说明是系统级的问题,和你的VB代码无关,重点排查网络打印机的状态。
- 如果手动操作正常,那才需要回到代码层面找问题。
2. 定位异常的网络打印机
既然都是网络打印机,很可能是某台打印机的网络连接中断、驱动崩溃或设备离线,导致Windows枚举时无限等待响应:
- 尝试逐个移除网络打印机(先移除一台,测试程序是否恢复),逐步排查出导致阻塞的那台设备。
- 找到异常打印机后,更新它的驱动程序,或者重新添加打印机(确保网络路径可达)。
3. 查看系统事件日志找线索
打开Windows事件查看器,重点检查以下日志:
- 应用程序和服务日志 > Microsoft > Windows > PrintService > Operational:这里会记录打印服务的详细错误,比如某台打印机的驱动加载失败、连接超时等。
- 系统日志:查看是否有Print Spooler服务或RPC服务的异常记录(打印机枚举依赖RPC服务)。
4. 优化代码避免主线程阻塞
原来的代码在主线程同步遍历打印机列表,一旦枚举卡住,整个应用就会无响应。可以改成异步枚举+超时控制,既避免阻塞,又能记录异常:
Protected Overridable Async Sub SetPrinter(ByRef data As IData, ByRef reportdoc As ReportDocument) Dim printer As String Dim paperorientation As String Dim papersource As String Dim papersize As String Dim devicename As String devicename = data.P_DeviceName If Not devicename Is Nothing AndAlso devicename.Trim <> "" Then paperorientation = reportdoc.PrintOptions.PaperOrientation papersize = reportdoc.PrintOptions.PaperSize papersource = reportdoc.PrintOptions.PaperSource devicename = devicename.Trim.ToUpper() ' 异步执行打印机枚举,设置5秒超时 Dim targetPrinter As String = Await Task.Run(Function() Dim result As String = Nothing Dim timeoutMs As Integer = 5000 Dim startTick As Integer = Environment.TickCount For Each p In System.Drawing.Printing.PrinterSettings.InstalledPrinters ' 检查是否超时 If Environment.TickCount - startTick > timeoutMs Then System.Diagnostics.Trace.WriteLine("打印机枚举超时,未找到目标打印机:" & devicename) Exit For End If If p.ToUpper() = devicename Then result = p Exit For End If Next Return result End Function) If targetPrinter IsNot Nothing Then reportdoc.PrintOptions.PrinterName = targetPrinter reportdoc.PrintOptions.PaperOrientation = CShort(paperorientation) reportdoc.PrintOptions.PaperSource = CShort(papersource) If CDbl(papersize) > 0 And CDbl(papersize) < 42 Then reportdoc.PrintOptions.PaperSize = CShort(papersize) End If End If End If End Sub
这个改动会把枚举逻辑放到后台线程,即使卡住也不会影响主线程,还能通过日志记录超时情况。
5. 清理打印机缓存
Windows会缓存打印机信息,缓存损坏也可能导致枚举异常:
- 停止Print Spooler服务(命令行:
net stop spooler) - 清空
C:\Windows\System32\spool\PRINTERS文件夹内的所有文件 - 重启Print Spooler服务(命令行:
net start spooler)
虽然你说重启打印服务没用,但清理缓存后再重启服务可能解决问题。
6. 检查Print Spooler的依赖服务
打印机枚举依赖RPC(Remote Procedure Call)服务,确保RPC服务正常运行:
- 打开服务管理器,找到「Remote Procedure Call (RPC)」,确认状态是「正在运行」,且启动类型为「自动」。
- 另外,如果是IPP协议的网络打印机,还要确保HTTP服务正常运行。
内容的提问来源于stack exchange,提问作者Debs
相关产品推荐
相关产品推荐

