在关闭程序之前在Windows 7关闭时运行批处理文件(最好是按下电源按钮)

lim*_*ime 8 vmware shutdown batch-file acpi windows-7

我有一个Windows 7机器,其中包含多个启动时启动的VMWare Player机器.我使用WMWare VIX和批处理文件关闭虚拟机,如下所示:

"C:\path\to\VMWare VIX\vmrun.exe" -T player stop "C:\path\to\machine.vmx" soft
Run Code Online (Sandbox Code Playgroud)

我想要完成的是在主机关闭时运行这些命令,这样我就不需要单独关闭每个VM.部署后,可能只需短按ACPI电源按钮即可开始关机,而不是从"开始"菜单开始.我试过的方法不起作用(至少不够好):

  1. 组策略 - 最明显的方法,但在Windows 7中,"异步"运行关闭脚本的选项已经消失.
    结果是,Windows 首先告诉所有打开的窗口关闭,虚拟机响应它们正在使用,并且您将获得"强制关闭"对话框.只有 VMWare Player和其他所有内容都关闭后,脚本才会运行,没有用.
    你认为这可能会改变,但我想我记得看到一些正式的MS注意到"不,抱歉".但是找不到链接.

  2. 使用一个批处理文件关闭所有虚拟机,然后将主机关闭为桌面快捷方式,而不是通常的关机按钮. - 工作,这就是我在开发过程中正在使用的东西.
    但是使用ACPI电源按钮启动正常关机,结果与之前相同,如果每天打开和关闭机器的最终用户不需要使用显示器和鼠标,那就更好了.
    所以我现在正在谷歌搜索是一种修改按下物理电源按钮时调用的操作的方法.Windows允许您在一些不同的操作(如睡眠,休眠,重启等)之间进行选择,但是您可以将其更改为"运行此.bat"吗?或者可能完全改变shutdown命令的行为?

  3. 以编程方式拦截关闭消息,中止关闭,运行批处理文件,重新启动关闭.关于拦截关闭的讨论已经有了一些讨论,例如这里,这里这里,但是我仍然在所有语言中都使用了n00b,除了Ruby或Java之外,我真的可以理解在这种情况下是否以及如何完成它.如果有人可以澄清如何实际完成这项工作(不会卡在"强制关闭"屏幕上),那么我很想尝试你提供的任何语言.

lim*_*ime 3

好的,所以我找到了一个适合我的解决方案;一个名为 AutoHotkey_L 的工具以及根据AutoHotkey 论坛上的这些 帖子制作的脚本。

这是我正在使用的代码,我建议阅读文档中的 AutoHotkey 命令。当我了解代码的实际用途时,我正在调整代码,但目前这是可行的。:)

#NoEnv
#Persistent
SendMode Input
SetWorkingDir %A_ScriptDir%
SetTimer, RunBeforeShutdown, Off

Gui,+LastFound
hwnd:=WinExist()
DllCall("ShutdownBlockReasonCreate","Uint",hwnd,"Str","")
DllCall("kernel32.dll\SetProcessShutdownParameters", UInt, 0x4FF, UInt, 0)
;puts us first in line for getting the shutdown call, i guess?
OnMessage(0x11, "WM_QUERYENDSESSION")
Return

WM_QUERYENDSESSION(wParam, lParam)
{
    ENDSESSION_Logoff = 2147483648
    If (lParam == ENDSESSION_Logoff) {
        global EventType = "Logoff"
    } Else {
        global EventType = "Shutdown"
        ;no way to distinguish between shutdown and restart
    }

    SetTimer, RunBeforeShutdown, On
    Return false
}

runBeforeShutdown:
    SetTimer, RunBeforeShutdown, Off
    Sleep, 1000
    SendInput, {ENTER}  ; gets us past the 'Force shudown' screen
    Sleep, 1000
    #SingleInstance, Force
    DllCall("ShutdownBlockReasonDestroy","Uint",hwnd)
    ; **** Your commands go here ****
    RunWait shutdown.bat
    ; ********

    If (EventType == "Logoff") {
        Shutdown, 0
    } Else {
        Shutdown, 1
    }
    Reload
Return
Run Code Online (Sandbox Code Playgroud)

所以现在它只区分注销和关机,但这篇文章有一个简单的 HTML GUI,可以让用户选择是否要重新启动、休眠等。

就我而言,无论 VMware 是否正在运行,都可以中断关闭并运行批处理文件,但您可以为其设置一个条件,例如如下所示:

IfWinExist, ahk_class VMPlayerFrame {
    SetTimer, RunBeforeShutdown, On
    Return false
} Else { 
    Return true
}
Run Code Online (Sandbox Code Playgroud)

我已经遇到了此脚本的问题,例如当主机速度如此缓慢(内存泄漏)时,“强制关闭”屏幕不会及时出现以便脚本将其关闭。它可能会受益于跟踪尝试次数,以便在第一次尝试失败时可以强制关闭。

至少现在足够好了。毕竟我的项目甚至可能不需要虚拟化,但希望它可以帮助其他人。替代解决方案仍然很受欢迎。


归档时间:

查看次数:

18618 次

最近记录:

8 年,4 月 前