检测计划关机

10
我有一个cmd脚本,用于执行一组补丁,如果需要重新启动以避免出现补丁问题,它被设计为中止。我还想扩展脚本以在计划重新启动(例如通过“shutdown”命令)时中止,以尽可能避免补丁过程中的重新启动。不幸的是,我还没有找到除尝试安排另一个关机之外检测此类情况的方法,这会导致以下结果:

系统已经安排了关闭。(1190)

虽然理论上我可以使用这个方法,但我认为每次需要检查计划的重新启动时都吓唬登录用户并不是好的做法。我真正需要的是一种查询由“shutdown”命令修改的状态的方法。

这可行吗?我会满意任何不需要我在系统上永久运行应用程序以捕获关机事件(我甚至认为在触发关机之前甚至不会发送事件)的解决方案。

5个回答

4

我也遇到了同样的问题,在网上搜索了很久,但是没有找到有用的东西。

最终我开始试着尝试各种不同的方法。我能想到两种解决问题的方法。

事件查看器可以告诉你计划关机已经预定,但不能告诉你预定的时间。

一种想法是查询事件查看器以获取最近的系统关闭、最近预定的关闭和最近取消预定关闭。如果预定关闭比最近的取消或关闭更近,则正在进行一个关闭操作。 事件ID为: 1074表示启动预定关闭, 1075表示取消预定关闭,都在 Windows Logs/System 下 12表示系统启动 13表示系统关闭 (所有这些都在 Windows Logs/System 下)

我太懒了,不想在批处理文件中执行此操作,但我知道这是可能的。

所以这就是我最终的做法: 与其安排关闭操作,不如尝试中止它。如果没有关闭操作正在进行中,它会抛出错误(无法中止系统关闭,因为没有关闭正在进行中。(1116))。我认为这比安排关闭操作让用户感到恐慌要好得多。

这里是我编写的简单自动关闭脚本的代码副本,它在取消和开始预定关闭之间切换。

@echo off
shutdown /a
if errorlevel 1 call:shutdown
goto end

:shutdown
    set /p choice=Shutdown in how many minutes? 
    set /a mod=60
    set /a mod*=%choice%
    shutdown /s /t %mod%

:end

编辑 - 我重新审视了这个答案,因为我有更多的信息要添加。

以上解决方案将检测是否使用shutdown.exe命令使用/t参数安排了关机。

如果您需要确定Windows是否已安排关机(如在某些Windows更新后自动执行),则可以查询设置的注册表项。以下是PowerShell中的代码,但您可以编写批处理文件来执行相同的操作。

Test-Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending'

注意:如果使用shutdown.exe进行计划重启,此函数将不会返回真值,仅在Windows认为你的计算机需要重新启动时返回真值。


2
你可以使用以下命令:

Shutdown /a "取消计划关机"

然后再次使用shutdown创建另一个计划。


0

我想你可以使用 任务计划程序 API 枚举已安排的任务,并查看它们是否调用了 shutdown.exe。但我不确定这是否足够健壮。可能有多种方法可以安排关机。


是的,不幸的是有几种方法,到目前为止我还没有弄清楚“shutdown /r /t 60”命令如何安排计划。它似乎不是一个计划任务 - 可能是更低级别的东西,没有显式的API很难检测到:( - Ificator

0

也许你可以尝试通过调用ExitWindowsEx并设置一个较长的优雅期来启动关机,并检查返回代码ERROR_SHUTDOWN_IS_SCHEDULED,如果ExitWindosEx返回成功(表示你已成功安排了关机),立即调用AbortSystemShutdown


1
谢谢您的建议,不过我把它当做最后的选择,因为我真的不想让机器上的任何用户被周期性的“机器正在重新启动”、“只是开玩笑”的通知消息所混淆。 - Ificator

0

如果您的脚本正在设置关机,另一种方法是使用setx命令将%date%和%time%变量保存到全局环境中。然后,您可以在下一次调用脚本时检查这些变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接