☰
Print Spooler服务自动重启脚本:原理、部署与故障排查指南
2026/10/8 3:43:32 网站建设 项目流程

简介:Windows系统自带的Print Spooler服务频繁异常关闭时,一套自动启动与恢复方案可有效应对。Print Spooler负责管理打印机队列并依次派发打印任务,一旦服务中断,所有打印作业都会停滞。资源内置的批处理脚本可配置服务随系统启动自动运行,另一脚本用于取消该配置,便于灵活切换。

压缩包共10个文件,以批处理、可执行程序、配置文档、操作手册及安装日志为主,仅22KB。监控程序会定期检测Print Spooler状态,停止时自动拉起;配置文件可调整行为;操作手册提供部署与排错指引;安装日志辅助排查。适合个人及企业IT运维快速部署,尤其适用于打印量大的办公环境。

目前已由4020人学习下载,对依赖稳定打印功能的场景尤为实用。读者能获得可直接运行的监控程序、安装与卸载脚本,以及清晰的排错文档,即使不熟悉命令行也能按手册完成设置并解决打印服务中断造成的打印失败问题。

1. 打印服务停摆之后:这个自动启动程序到底帮你干什么

很多服务器管理员都遇到过这种场景:凌晨一点财务报表打不出来,远程连上去一看,打印服务print spooler自动启动程序根本没派上用场,Print Spooler 服务停在“已停止”状态,队列里积压了十几份作业。这个自动启动程序要解决的,就是用脚本或计划任务监视服务状态,发现 Print Spooler 掉了就自动拉起来,同时记录日志、保留现场,让你早上到现场时能快速判断问题出在驱动、权限还是硬件。它适合两类人:一类是管着几十台 Windows 服务器和共享打印机的运维,另一类是帮中小企业维护打印设备的外包工程师。接下来我会从服务原理讲到脚本部署,再到 Windows Server 2012 上打印服务安装的坑,最后给出我踩过的五个雷区,保证你照着做不会翻车。

2. 先搞懂 Print Spooler:为什么它一停打印机全傻

2.1 Print Spooler 就是打印机的“总调度”

Print Spooler 在 Windows 服务体系里扮演的角色,可以简单理解成打印机任务的交通警察。记事本、Word、ERP 系统把打印内容交给 GDI 或 DirectWrite 接口后,任务并不会直接冲进打印机,而是先交给 Spooler 服务,由它写入system32\spool\printers目录暂存,然后按优先级分发到对应打印机的处理器。这个设计让应用不用等着打印机慢慢吐纸,用户点一次打印就能立刻去干别的事。

如果 Spooler 停掉,整个流程立刻卡死:新任务进不了队列,已排队任务不会继续走,甚至已经半打印的文档会残留在打印机的临时文件里。对共享打印机环境来说,影响面更大——服务器上的 Spooler 一挂,所有客户端的打印请求全部失败,通常报“无法连接到打印 服务”。有一次我把打印机拔了重插,结果发现问题不在 USB,而是 Spooler 被安全厂商的驱动改崩了,这正是这个自动启动程序要预防的核心场景。

2.2 手动检测和启动:三条命令与一行判断

在写自动启动脚本之前,先掌握手动排查的三板斧。第一板斧是查看服务状态,我习惯用Get-Service是因为可以配合分支判断写脚本,但命令行临时处理时sc和net更直接。

Get-Service -Name Spooler

这行命令返回的是服务状态:Stopped、Running还是Paused。注意Status只是最基础的判断,如果你拿到的服务是“启动类型禁用”,那Get-Service再快也没用,后面我会专门说 GPO 导致的坑。

sc query Spooler

sc query显示的状态信息更细,包括服务进程 PID、服务类型和退出代码。当你怀疑 Spooler 启了又死时,看sc query里的STATE字段能发现是不是卡在START_PENDING。

net start Spooler

这是最朴素的启动命令,适合临时救火。管理员权限下运行,如果服务启动失败会直接返回系统错误码,比如 1058(服务禁用)或 1069(登录失败)。我一般把这三条命令串起来用:先sc query看状态,再net start启动,最后Get-Service确认结果。手动能跑通,脚本才有意义。

2.3 服务恢复选项:系统自带的“自启动”为什么不够用

在services.msc里找到 Print Spooler,打开属性切到“恢复”选项卡,你会发现 Windows 其实自带“失败后重新启动服务”的选项。默认设置往往是“首次失败:重新启动服务”,这让很多人误以为系统已经能自动拉起 Spooler,不需要额外写程序。

但这个恢复机制有非常明显的盲区:它只在服务“意外终止”时触发。用任务管理器结束进程、服务崩溃退出的情况它管,但管理员手动停止服务、系统关机前正常停止、或者服务因依赖关系无法启动时,恢复选项卡根本不会执行。我见过最典型的情况是,安全软件清理了 Spooler 的注册表项,服务启动失败但状态还不是“停止”,而是DELETE_PENDING,这时候恢复设置完全失效。

所以真正可靠的自动启动程序不能只依赖服务自带的恢复机制,必须有一个外部看门狗。它可以是个计划任务,每隔几分钟检查一次服务状态,发现不是Running就尝试启动;也可以是 Windows 服务,监听 Service Control Manager 事件。这个资源里用的方案是基于计划任务加 PowerShell 脚本的组合,部署成本低,而且能在事件日志里留下明确的启动记录。

3. 把自动启动程序跑起来:脚本拆解与关键参数

3.1 脚本结构:服务检测、启动与防抖动

这套自动启动程序的核心是一个 PowerShell 监测脚本,整体逻辑分成三层:检查状态、尝试启动、结果记录。先看主体代码。

param( [string]$ServiceName = "Spooler", [int]$MaxRetry = 3, [int]$RetryIntervalSeconds = 10, [string]$LogPath = "C:\Scripts\PrintSpoolerAutoStart.log" ) function Write-Log { param([string]$Message) $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" "$timestamp $Message" | Out-File -FilePath $LogPath -Append -Encoding UTF8 } $service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue if (-not $service) { Write-Log "ERROR: 服务 $ServiceName 不存在,请检查名称" exit 1 } if ($service.Status -eq "Running") { Write-Log "INFO: $ServiceName 状态正常,无需处理" exit 0 } # 状态不是 Running,开始尝试拉起 $attempt = 0 do { $attempt++ Write-Log "WARN: 第 $attempt 次尝试启动 $ServiceName,当前状态 $($service.Status)" try { Start-Service -Name $ServiceName -ErrorAction Stop Start-Sleep -Seconds 3 $service = Get-Service -Name $ServiceName } catch { $errorMsg = $_.Exception.Message Write-Log "ERROR: 启动失败 $errorMsg" } if ($service.Status -ne "Running" -and $attempt -lt $MaxRetry) { Write-Log "WARN: 等待 $RetryIntervalSeconds 秒后重试" Start-Sleep -Seconds $RetryIntervalSeconds } } while ($service.Status -ne "Running" -and $attempt -lt $MaxRetry) if ($service.Status -eq "Running") { Write-Log "INFO: $ServiceName 已恢复运行,共尝试 $attempt 次" } else { Write-Log "ERROR: 多次启动失败,需要人工介入,请在事件查看器中排查原因" exit 2 }

这个脚本有几个值得注意的参数。MaxRetry设成 3,是因为第一次启动失败后常有驱动加载延迟,马上重试大概率会继续失败,间隔 10 秒是给系统一个缓冲。RetryIntervalSeconds是重试间隔,单位秒,建议不要小于 5,否则脚本会像重机枪一样连续触发启动请求,反而增加服务崩溃风险。日志路径一定要放在固定位置,而且要给当前用户写入权限,否则脚本会在日志这一步静默失败,排查时什么线索都没有。

3.2 部署到生产机:权限、计划任务与开机启动

脚本本身不会无缘无故跑起来,部署的关键是把它挂到任务计划程序里。最常见的做法是设置一个每 5 分钟运行一次的计划任务,触发条件不选“用户登录时”,而是选择“计算机启动时”或“按计划”。注意执行身份要选SYSTEM或具有管理员权限的账户。

下面是用schtasks创建计划任务的命令,适合批量部署。

schtasks /Create /TN "PrintSpoolerMonitor" /TR "powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File C:\Scripts\CheckPrintSpooler.ps1" /SC MINUTE /MO 5 /RU SYSTEM /RL HIGHEST

/RU SYSTEM解决权限不足问题,普通用户启动服务会有一个隐藏坑:命令行不报错,但服务实际没起来,因为进程令牌没有SeServiceLogonRight。用SYSTEM账户不仅规避权限问题,还能让脚本在无用户会话的情况下正常工作。/RL HIGHEST是提高计划任务运行优先级,避免它被其他任务排队拖后。

部署完成后,建议马上手动执行一次计划任务验证。在“任务计划程序”里右键选择“运行”,然后去服务管理器看 Spooler 状态和日志文件。如果日志里出现ERROR: 服务不存在,八成是脚本里传参写错了,检查ServiceName是不是默认的Spooler,别被中文系统的“打印后台处理程序”迷惑。

3.3 参数调整:轮询间隔、日志输出与打印机恢复

这套程序的默认参数适合大多数场景,但实际部署时建议按环境调整。轮询间隔跟打印机使用频率相关,业务集中且打印量大的服务器,5 分钟太慢,建议缩短到 1 分钟;打印量小且有 UPS 保障的办公环境,10 分钟甚至 15 分钟都行,毕竟 Spooler 没你想的那么脆弱。这里把任务计划改成每分钟触发一次即可。

schtasks /Change /TN "PrintSpoolerMonitor" /SC MINUTE /MO 1

日志文件的处理也要留个心眼。脚本是用Out-File -Append追加写入,时间长了文件会膨胀。我一般会额外加一个清理逻辑,保留最近 30 天的日志行:

$maxLines = 5000 if ((Get-Content $LogPath | Measure-Object -Line).Lines -gt $maxLines) { Get-Content $LogPath | Select-Object -Last 2000 | Set-Content $LogPath }

另一个容易忽略的参数是打印机恢复后的动作。有些打印机在 Spooler 挂掉后会进入脱机状态,即便服务拉起来了也不自动恢复。可以在脚本成功启动服务后,调用 Windows 自带的Unidrv或厂商命令唤醒打印机队列。但厂商命令差异大,我习惯先不做这一步,优先保证服务状态恢复,再让打印机厂商的监控工具去处理连接状态,重点避免因为强行发送 WMI 指令导致驱动加载失败。

4. 在 Windows Server 2012 上装好打印服务:图形界面和命令行两条路

4.1 添加打印和文件服务角色:图形界面的入口

如果你要在 Windows Server 2012 上部署打印服务,下载资源里的自启动脚本之前,得先把“打印和文件服务”角色装上。这个角色的名称在国内系统和英文系统下会稍有差异,中文系统显示“打印和文件服务”,英文是Print and Document Services。

打开服务器管理器,点“添加角色和功能”,一直下一步到“选择服务器角色”,勾选“打印和文件服务”。注意这里不要漏掉“打印服务”子组件,很多人在这一步选了父级就点下一步,结果装完发现根本没有 Print Spooler 的图形管理入口。另外“打印服务”下面还有“Internet 打印”“LPD 服务”这些可选子项,一般局域网打印用不上,但如果你的打印机扫描仪支持网络发送到指定 IP,就可能需要 LPD。

安装过程大概一两分钟,完成后在“工具”菜单里会出现“打印管理”。这里能管理打印服务器、驱动、表单、端口。第一次装完,Spooler 服务默认是自动启动的,但千万别急着配打印机——先确认服务状态,再考虑是否马上挂上自启动监控脚本,因为角色安装可能触发服务重启,脚本会被任务计划调用一次。

4.2 命令行安装 Print Server 角色:PowerShell 一句搞定

动手能力强的工程师更愿意用 PowerShell 一键安装,尤其是在核心版 Server 2012 上,没有图形界面,只能用命令行。命令其实很简单:

Install-WindowsFeature -Name Print-Services -IncludeManagementTools

这条命令会安装打印服务和所有管理工具。-IncludeManagementTools参数很关键,它会把“打印管理”控制台、PowerShell 模块一起装上。如果你只想装服务端、不装管理工具,可以不带这个参数,但后续你会发现自己连Get-PrinterPort都用不了,排查问题非常痛苦。

安装完成后还可以用Restart-Service -Name Spooler -Force确保服务干净启动。这里有个细节:Windows Server 2012 的默认 PowerShell 版本是 3.0,Install-WindowsFeature可用,但如果你拿到的系统是 2008 R2,这个命令就不存在,只能用Add-WindowsFeature或者配合 DISM 使用。下载脚本资源时,我记得里面的说明文档明确写了“仅适用于 Windows Server 2012 及以上”,这也是为什么围绕这个系统讨论的坑这么多。

4.3 共享打印机与驱动分发:装完不等于能用

打印服务角色装好,只是服务器的“打印能力”就绪。实际使用中,你需要添加打印机端口、安装驱动、设置共享名称,然后通过组策略或手动 UNC 路径把打印机分发到客户端。很多新手在这步被坑:角色装完,Spooler 也在跑,但客户端连不上,因为打印机本身没有添加成功。

添加网络打印机时,我用的是Add-Printer加Add-PrinterPort的组合:

$portName = "192.168.10.50" Add-PrinterPort -Name $portName -PrinterHostAddress $portName Add-Printer -Name "财务打印机" -PortName $portName -DriverName "HP LaserJet P2035" -Shared -ShareName "FinancePrinter"

DriverName必须和服务器上已安装的驱动名称完全一致,大小写不敏感但空格和版本号不能错。如果你不确定驱动名,先用Get-PrinterDriver列出来看看,再执行上述命令。共享打印机的坑在于驱动分发:客户端如果是 32 位,服务器需要额外安装 x86 驱动,否则连接时会报“找不到驱动程序”。这个自启动脚本不会帮你解决驱动兼容性,它只管服务状态,千万不要把它当成万能修复工具。

5. 避坑实战:打印服务自启动最常见的五个故障点

5.1 现象:计划任务显示运行,服务还是停了

你打开任务计划程序,平均最后一次运行结果显示“已完成”,但 Spooler 就是没起来。等我从日志文件里看到的是:脚本检测到服务状态正常后直接退出,根本没想到接下来服务又崩了。

原因:服务稳定运行了几分钟后才崩溃,脚本只做“点判断”不做“持续看护”。解决:把轮询间隔从 5 分钟改到 30 秒,并且把日志里每次检测都打点。我后来在脚本里加了Start-Sleep前记录当前状态和 PID,确认是不是脚本跑完导致服务崩溃。

5.2 现象:服务启动失败,事件日志报“拒绝访问”

启动脚本没有明显报错,但 Spooler 服务启动后很快停止,系统日志里有错误 ID 7000,提示服务账户没有足够的权限去登录或访问某个文件。

原因:Spooler 服务默认以LocalSystem运行,但有时系统或安全软件会把服务账户改成普通用户,或者 ACL 权限被清理过。解决:打开services.msc,找到“打印后台处理程序”,进属性,把“登录身份”改回“本地系统账户”,然后重启服务。要注意,驱动文件的 ACL 也需要检查,用icacls给C:\Windows\System32\spool\drivers加上 SYSTEM 完全控制。

5.3 现象:脚本把服务拉起来了,打印队列还是卡住

Spooler 恢复了,但客户端提交的任务一直显示“正在打印”,过一会儿变成“错误”。进到system32\spool\printers里看,残留了一堆.shd和.spl文件。

原因:服务崩溃时打了一半的临时文件没有清理,重新启动后 Spooler 尝试恢复这些损坏的任务,结果被卡死。解决:服务启动后,在脚本里加一句清理逻辑:

Get-ChildItem "$env:SystemRoot\System32\spool\printers" -ErrorAction SilentlyContinue | Remove-Item -Force

注意不要把正在活动打印任务的目录清掉,我一般会加个判断:文件修改时间超过 15 分钟才删除,这样刚产生的新任务不会被误伤。

5.4 现象:域策略把自启动操作又改回去了

你费劲配置好服务恢复选项和启动类型,过一个月客户端和服务器上的 Spooler 启动类型又变回“手动”,或者干脆是“禁用”。

原因:组策略里的打印机_服务启动类型或Print Spooler 的恢复操作被域管理员强制下发,覆盖了本地配置。解决:这种情况不能硬刚,需要修改 GPO 或者在你的自启动脚本里加入策略对抗逻辑。更稳妥的做法是在脚本里直接调用Set-Service -StartupType Automatic,每次执行时把启动类型拉回来:

Set-Service -Name Spooler -StartupType Automatic

如果连Set-Service都被策略限制,那只能检查“注册表策略”里HKLM\SYSTEM\CurrentControlSet\Services\Spooler\Start的值,并确保在计划任务里设置了“最高权限”。

5.5 现象:打印机驱动导致 Spooler 反复崩溃

服务日志显示 Spooler 频繁崩溃,崩溃前总是加载某个第三方驱动,比如电商用的电子面单打印驱动或者老式针式打印机驱动。

原因:第三方驱动写得有问题,进程崩溃时把 Spooler 一起带崩。解决:先确认驱动文件名,从事件日志里找到dllhost.exe的加载路径。我有一次排查半天,发现是扫码枪厂商的一个端口监视器 DLL 靠不住,直接在注册表HKLM\SYSTEM\CurrentControlSet\Control\Print\Monitors里删掉那个键项。删之前记得备份注册表,这招治标不治本,但能让打印机重新工作。自动启动程序可以救急,但驱动兼容性问题一定要从厂商补丁入手,否则脚本会一天拉起来十几次。

6. 进阶用法:把自启动脚本升级成打印自愈系统

6.1 用服务状态和事件 ID 组合触发更精准

固定间隔轮询是保险做法,但高级一点的监控可以不依赖轮询,而是订阅 System 事件日志。比如 Spooler 崩溃时,Windows 会写事件 ID 7031 或 7034,有计划任务可以基于事件启动,这样响应是秒级,不用等 5 分钟。把计划任务触发条件从“按计划”改成“自定义事件”:

<QueryList> <Query> <Select Path="System">*[System[Provider[@Name='Service Control Manager'] and (EventID=7031 or EventID=7034)]]</Select> </Query> </QueryList>

这个 XML 可以作为任务触发条件,但要注意事件日志可能被清掉,所以我会保留原有的每 5 分钟轮询作为兜底,双保险。

6.2 日志清洗与告警:失败后仍能回溯现场

自启动程序跑久了,最怕的是日志太大不加区分。我给脚本加了单独的失败日志文件,每次启动失败都会写进去,并且不追加,直接覆盖。这样一旦用户反馈打印机坏了,我能第一时间看到最近一次失败时间、失败原因和尝试次数。有条件的话,可以把失败记录发送到企业微信或邮件,这个资源里带了一个简单的 SMTP 邮件发送例子,用的还是 PowerShell 自带Send-MailMessage,不过在 Windows Server 2012 上要注意 TLS 版本配置,否则邮件会卡在连接超时。

6.3 验证自愈是否生效:演练一次真正的打印故障

最后一件事,我强烈建议你在部署后主动制造一次故障来验证自愈逻辑。方法很简单:以管理员身份运行Stop-Service -Name Spooler -Force,强行终止服务,然后等 5 分钟看计划任务有没有把它拉起来。

我那次演练差点翻车,停服务后脚本没有立刻拉起来,日志显示“服务状态正常,无需处理”,仔细检查发现我停的是Spooler,但脚本里写的是Print Spooler,服务名大小写和本地化名称不一致。从那以后,我每部署一个新环境都会先跑一遍演练流程,确认脚本确实把状态拉起来了才离开。这种验证手段比看十遍代码都有用。希望我的这段经历能帮到你,少走一点我走过的弯路。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询