Запустите пакетный файл при завершении работы Windows 7 перед закрытием программ (желательно при нажатии кнопки питания) - PullRequest
8 голосов
/ 24 января 2011

У меня есть Windows 7 с несколькими компьютерами VMWare Player, которые запускаются при загрузке.Я использую WMWare VIX и командный файл для выключения виртуальных машин, например:

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

Я хочу выполнить эти команды, когда хост-машина выключена, так что мне не нужнозакрыть каждую виртуальную машину отдельно.При развертывании выключения, скорее всего, начнутся с короткого нажатия кнопки питания ACPI, а не из меню «Пуск».Способы, которые я пробовал, не работают (по крайней мере, недостаточно хорошо):

  1. Групповые политики - самый очевидный путь, но в Windows 7 есть возможность запустить выключениесценарии «асинхронно» пропали.
    В результате Windows first сообщает всем открытым окнам закрыть, виртуальные машины отвечают, что они используются, и вы получаете диалоговое окно «Принудительное закрытие».Только после VMWare Player и все остальное закрыто, скрипты запускаются, без толку.
    Вы могли бы подумать, что это можно изменить, но я думаю, что я помню, как увидел какую-то официальную заметку MS в духе"Прошу прощения, но нет".Однако не удается найти ссылку.

  2. Используйте один пакетный файл, который закрывает все виртуальные машины, а затем отключает хост в качестве ярлыка на рабочем столе вместо обычной кнопки выключения.- Работает, и это то, что я сейчас использую при разработке.
    Но использование кнопки питания ACPI запускает нормальное отключение с тем же результатом, что и раньше, и было бы лучше, если бы конечный пользователь включал машинуДля ежедневного включения и выключения не нужно использовать монитор и мышь.
    Так что в данный момент я пытаюсь найти способ изменить действие, вызываемое при нажатии кнопки физического питания.Windows позволяет выбирать между различными действиями, такими как «Сон», «Спящий режим», «Перезагрузка» и т. Д., Но не могли бы вы изменить это на «Запустить этот .bat»?Или может вообще изменить поведение команды выключения?

  3. Программно перехватить сообщение о выключении, прервать завершение работы, запустить пакетный файл, повторно запустить выключение.Было некоторое обсуждение перехвата выключения, например здесь , здесь и здесь , но я все еще слишком много n00b во всех языках, кроме, может быть, Ruby илиJava, чтобы действительно понять, если и как это можно сделать в этом случае.Если кто-то может уточнить, как на самом деле сделать эту работу (не застревая на экране «Принудительное закрытие»), тогда я с удовольствием попробую любой язык, который вы предлагаете.

Ответы [ 3 ]

3 голосов
/ 09 марта 2011

Хорошо, я нашел решение, которое сработало для меня;инструмент 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
}

У меня уже были проблемы с этим сценарием, например, когда хост настолько замедлен (утечка памяти), что экран «Force shudown» не появится вовремя, чтобы скрипт закрыл его.И, вероятно, было бы полезно отслеживать количество попыток, чтобы можно было принудительно завершить работу, если первая попытка не удалась.

По крайней мере, на данный момент достаточно.И мне может даже не понадобиться виртуализация для моего проекта, но, надеюсь, она может помочь кому-то еще.Альтернативные решения по-прежнему очень приветствуются.

1 голос
/ 02 ноября 2011

Я придумал это решение той же проблемы: http://communities.vmware.com/thread/334740

Хитрость в преодолении «принудительного закрытия» заключается в том, чтобы сначала приостановить / остановить все виртуальные машины, а затем повторно выполнить завершение работы в том же сценарии. Кажется, это работает для меня.

0 голосов
/ 01 февраля 2011

Рабочая станция предпочитает «Поддерживать работу виртуальных машин после закрытия рабочей станции».У плеера VMware есть такая же опция?

Как я вижу, как это работает: Включите вышеуказанное предпочтение.Окно закрывается, оставляя виртуальные машины работающими.Затем процесс выключения может продолжаться до вашего сценария с # 1, который должен завершить / приостановить виртуальные машины перед завершением.

У меня нет виртуальных машин Player, поэтому я не могу проверить это, нонадеюсь, это поможет.

...