8

I have a Windows 7 box with multiple VMWare Player machines that are started on boot. I use WMWare VIX and a batch file to shutdown the virtual machines like so:

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

What I want to accomplish is to run these commands when the host machine is shut down, so that I don't need to shut down each VM separately. When deployed, shutdowns will likely be started with a short press of the ACPI power button, not from the Start menu. Ways I've tried that don't work (at least not well enough):

  1. Group Policies - The most obvious way to go, but in Windows 7, the option to run shutdown scripts 'asynchronously' is gone.
    The result is that Windows first tells all open windows to close, the VMs respond that they are in use and you get the 'Force close' dialog. Only after VMWare Player and everything else is closed are the scripts run, to no use.
    You'd think this could be changed, but I think I remember seeing some official MS note along the lines of "nope, sorry". Can't find the link though.

  2. Use one batch file that closes all VMs and then shutdowns the host as a desktop shortcut instead of the usual shutdown button. - Works, and that's about what I'm using right now while developing.
    But using the ACPI power button initiates a normal shutdown with the same result as earlier, and it would be better if the end-user who turns the machine on and off on a daily basis wouldn't need to use a monitor and mouse.
    So what I'm googling for at the moment is a way to modify the action called when pressing the physical power button. Windows allows you to choose between some different actions like Sleep, Hibernate, Restart etc, but could you change that into 'Run this .bat'? Or maybe change the behaviour of the shutdown command altogether?

  3. Programmatically intercept the shutdown message, abort shutdown, run batch file, re-initiate shutdown. There has been some discussion on intercepting shutdown e.g. here, here and here, but I'm still too much of a n00b in all languages except maybe Ruby or Java to really understand if and how it could be done in this case. If someone can clarify how to actually make this work (without getting stuck on the 'Force close' screen) then I'm eager to try out any language you offer.

Cœur
  • 32,421
  • 21
  • 173
  • 232
lime
  • 6,193
  • 3
  • 36
  • 48

3 Answers3

3

Okay, so i found a solution that worked for me; a tool called AutoHotkey_L and a script made according to these threads on the AutoHotkey forums.

This is the code I'm using, and I suggest reading up on AutoHotkey commands in the documentation. I'm tweaking the code as I learn what it's actually doing, but for now this works. :)

#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

So right now it only distinguishes between logoff and shutdown, but this post has a simple GUI in HTML that lets the user choose if they want to restart, hibernate etc.

In my case it's okay to interrupt shutdown and run the batch file regardless of whether VMware is running or not, but you can set a condition for it for example like so:

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

I have already run into problems with this script, like when the host is so slowed down (memory leakage) that the "Force shudown" screen won't appear in time for the script to close it. And it would probably benefit from keeping track of the number of tries, so that it could shutdown forcibly if the first try fails.

Good enough for now at least. And I may not even need virtualization for my project after all, but hopefully it can help someone else. Alternative solutions are still very welcome.

lime
  • 6,193
  • 3
  • 36
  • 48
1

I have come up with this solution to the same problem: http://communities.vmware.com/thread/334740

The trick to get past the "force close" is to first suspend/stop all VMs then re-issue the shutdown in the same script. It seems to work for me.

Peter O.
  • 28,965
  • 14
  • 72
  • 87
Wayne H
  • 11
  • 1
  • 1
    I am no longer able to try this out, but it looks promising. Would you be able to describe your final setup? It would be good for future readers to know what specific settings worked in the end. – lime Jan 26 '12 at 14:29
0

Workstation has a preference to 'Keep VMs running after Workstation closes'. Does VMware player have the same option?

The way I see this working: Enable the above preference. The window closes, leaving the VMs running. The shutdown process can then continue to your script from #1, which should shutdown/suspend the VMs before terminating.

I don't have any Player VMs myself, so I can't test this out, but I hope it helps.

Evan Powell
  • 900
  • 4
  • 4
  • In my experience, most Workstations preferences can be manually set in Player by modifying either the .vmx file on per VM basis or the preferences.ini in %appdata%\VMware. ([Sanbarrow.com](http://sanbarrow.com/vmx.html) has excellent reference on what parameters to set.) I tried setting `pref.backgroundOnClose = "true"` in preferences.ini, but it still shuts down on closing the window. Also, on shutdown I still get stuck on the 'Force close' screen. But great idea, I'll play around with the settings and report back. – lime Feb 03 '11 at 13:06
  • Okay, so the parameter is `pref.vmplayer.exit.vmAction = "disconnect"` and it does what it says when manually closing (with a bonus error message on Win7, not so on XP). But when shutting down the host Player reports as always that the machine is in use and will not close even into this disconnected state. Might try with Workstation, but I'm doubtful. – lime Feb 03 '11 at 14:49