8

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

"C:\path\to\VMWare VIX\vmrun.exe" -T player stop "C:\path\to\machine.vmx" soft

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

  1. 组策略 - 最明显的方法,但在 Windows 7 中,“异步”运行关闭脚本的选项消失了。
    结果是 Windows首先告诉所有打开的窗口关闭,VM 响应它们正在使用,然后您会看到“强制关闭”对话框。只有关闭 VMWare Player 和其他所有内容后,脚本才会运行,但没有任何用处。
    你会认为这可以改变,但我想我记得看到一些官方的 MS 注释,上面写着“不,抱歉”。虽然找不到链接。

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

  3. 以编程方式拦截关机消息,中止关机,运行批处理文件,重新启动关机。已经有一些关于拦截关机的讨论,例如这里这里这里,但是除了 Ruby 或 Java 之外,我仍然对所有语言都过于熟悉,无法真正理解在这种情况下是否以及如何做到这一点。如果有人可以阐明如何实际完成这项工作(不会卡在“强制关闭”屏幕上),那么我很想尝试您提供的任何语言。

4

3 回答 3

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

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

在我的情况下,无论 VMware 是否正在运行,都可以中断关机并运行批处理文件,但您可以为它设置一个条件,例如:

IfWinExist, ahk_class VMPlayerFrame {
    SetTimer, RunBeforeShutdown, On
    Return false
} Else { 
    Return true
}

我已经遇到了这个脚本的问题,比如当主机速度太慢(内存泄漏)时,“强制关闭”屏幕不会及时出现让脚本关闭它。它可能会受益于跟踪尝试的次数,这样如果第一次尝试失败,它就可以强制关闭。

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

于 2011-03-09T14:56:11.137 回答
1

我想出了解决同一问题的方法:http: //communities.vmware.com/thread/334740

通过“强制关闭”的技巧是首先暂停/停止所有虚拟机,然后在同一脚本中重新发出关闭。它似乎对我有用。

于 2011-11-02T09:04:23.660 回答
0

Workstation 具有“在 Workstation 关闭后保持 VM 运行”的首选项。VMware播放器是否有相同的选项?

我看到这个工作的方式:启用上述首选项。窗口关闭,VM 继续运行。然后,关闭过程可以从 #1 继续执行您的脚本,该脚本应该在终止之前关闭/挂起 VM。

我自己没有任何 Player VM,所以我无法对此进行测试,但我希望它有所帮助。

于 2011-02-01T17:18:39.400 回答