概要
GUIウィンドウを表示し、指定した時刻もしくは指定した時間経過後に自動的にシャットダウンするアプリケーションです。
間違ってシャットダウンを実行してしまった時のために、最後に実行確認のダイアログを表示する安全設計。俺は自分を信用しない。
ソース
シャットダウン実行ダイアログの表示は[Win]+[Esc]に割り当てています。
ところでShutdown
コマンドの引数にある「実行後電源を切る」ってどういう機能なんですかね。Windows8.1/10用の機能?
/**
* シャットダウン実行ダイアログを表示し、シャットダウンを実行する。
*/
ConfirmShutdown() {
;実行種別の値格納変数
Static sImmediately
Static sAtTime
Static sAfterTime
;実行種別のウィンドウハンドル
Static sHwndImmediately
Static sHwndAtTime
Static sHwndAfterTime
;シャットダウン種別の値格納変数
Static sShutdown
Static sReboot
Static sLogoff
Static sForce
Static sAfterProcess
;実行種別のウィンドウハンドル
Static sHwndShutdown
Static sHwndReboot
Static sHwndLogoff
Static sHwndForce
Static sHwndAfterProcess
;指定時刻の値格納変数
Static sSpecifiedDate
Static sSpecifiedTime
;指定時刻のウィンドウハンドル
Static sHwndLabelSpecifiedDateTime
Static sHwndSpecifiedDate
Static sHwndSpecifiedTime
;指定経過時間の値格納変数
Static sHour
Static sMin
Static sSec
;指定経過時間のウィンドウハンドル
Static sHwndLabelAfterTime
Static sHwndHour
Static sHwndLabelHour
Static sHwndMin
Static sHwndLabelMin
Static sHwndSec
Static sHwndLabelSec
;現在設定中のタイマーの値格納変数
Static sTimerDate
Static sTimerTime
;現在設定中のタイマーのウィンドウハンドル
Static sHwndLabelTimer
Static sHwndTimerDate
Static sHwndTimerTime
;ボタンのウィンドウハンドル
Static sHwndExecute
Static sHwndCancel
Static sHwndClearTimer
;シャットダウン実行のGUIを作成
Gui, Shutdown:New, , シャットダウン実行
;最小化ボタン有効化・最大化ボタン無効化
Gui, Shutdown:+MinimizeBox -Resize
;メッセージ
Gui, Shutdown:Add, Text, Xm+0 W320, PCをシャットダウンします。`r`n実行種別とシャットダウン種別を選択して[実行]ボタンを押してください。`r`nタイマーをセットする場合は時間を入力してください。`r`n現在設定中のタイマーを解除する場合、[タイマー解除]ボタンを押してください。
;シャットダウン種別
Gui, Shutdown:Add, GroupBox, Xm+0 Ym+80 W320 H76, シャットダウン種別
Gui, Shutdown:Add, Radio, HwndsHwndShutdown Vsshutdown Xp+10 Yp+20 Group Checked, シャットダウン
Gui, Shutdown:Add, Radio, HwndsHwndReboot VsReboot, 再起動
Gui, Shutdown:Add, Radio, HwndsHwndLogoff VsLogoff, ログオフ
Gui, Shutdown:Add, Checkbox, X+80 Y+-30 HwndsHwndForce VsForce Checked, 強制的に実行
Gui, Shutdown:Add, Checkbox, HwndsHwndAfterProcess VsAfterProcess, 実行後電源を切る
;実行種別グループボックス
Gui, Shutdown:Add, GroupBox, Xm+0 Y+15 W320 H148, 実行種別
;指定時刻
Gui, Shutdown:Add, GroupBox, HwndsHwndLabelSpecifiedDateTime Xm+10 Yp+35 W300 H48,
Gui, Shutdown:Add, DateTime, HwndsHwndSpecifiedDate VsSpecifiedDate GCalcTime Xp+10 Yp+20 W120, yyyy年MM月dd日
Gui, Shutdown:Add, DateTime, HwndsHwndSpecifiedTime VsSpecifiedTime GCalcTime X+10 W70, Time
;指定経過時間
Gui, Shutdown:Add, GroupBox, HwndsHwndLabelAfterTime Xm+10 Y+15 W300 H48,
Gui, Shutdown:Add, Edit, HwndsHwndHour VsHour Xp+10 Yp+20 W50 Number,
Gui, Shutdown:Add, UpDown, ,
Gui, Shutdown:Add, Text, HwndsHwndLabelHour GCalcTime X+3 Yp+6, 時間
Gui, Shutdown:Add, Edit, HwndsHwndMin VsMin GCalcTime X+10 Yp-6 W50 Number,
Gui, Shutdown:Add, UpDown, Range-1-60,
Gui, Shutdown:Add, Text, HwndsHwndLabelMin X+3 Yp+6, 分
Gui, Shutdown:Add, Edit, HwndsHwndSec VsSec GCalcTime X+10 W50 Number Yp-6,
Gui, Shutdown:Add, UpDown, Range-1-60,
Gui, Shutdown:Add, Text, HwndsHwndLabelSec X+3 Yp+6, 秒 後
;現在設定中のタイマー
Gui, Shutdown:Add, GroupBox, HwndsHwndLabelTimer Xm+0 Y+26 W320 H48, 現在設定中のタイマー
Gui, Shutdown:Add, Edit, HwndsHwndTimerDate VsTimerDate Xp+10 Yp+20 W120 ReadOnly,
Gui, Shutdown:Add, Edit, HwndsHwndTimerTime VsTimerTime X+10 W70 ReadOnly,
;ボタン
Gui, Shutdown:Add, Button, HwndsHwndExecute GShutdownExec Xm+0 Y+20 W100 Default, 実行(&E)
Gui, Shutdown:Add, Button, HwndsHwndCancel GShutdownCancel X+10 W100, キャンセル(&C)
Gui, Shutdown:Add, Button, HwndsHwndClearTimer GClearTimer X+10 W100, タイマー解除(&T)
;実行種別ラジオボタン
Gui, Shutdown:Add, Radio, HwndsHwndImmediately VsImmediately GSelectType Xm+18 Ym+182 Group Checked, 即時実行
Gui, Shutdown:Add, Radio, HwndsHwndAtTime VsAtTime GSelectType, 指定時刻に実行
Gui, Shutdown:Add, Radio, HwndsHwndAfterTime VsAfterTime GSelectType Y+42, 指定時間経過後に実行
If (gShutdownTimer != "")
{
;シャットダウンタイマーが空でない場合、現在設定中のタイマー時刻を表示
FormatTime, vTimerDate, %gShutdownTimer%, yyyy年MM月dd日
FormatTime, vTimerTime, %gShutdownTimer%, HH:mm:ss
;GUIを更新
GuiControl, , %sHwndTimerDate%, %vTimerDate%
GuiControl, , %sHwndTimerTime%, %vTimerTime%
}
Else
{
;シャットダウンタイマーが空の場合、現在設定中のタイマーと[タイマー解除]ボタンを非活性
GuiControl, Disable, %sHwndLabelTimer%
GuiControl, Disable, %sHwndTimerDate%
GuiControl, Disable, %sHwndTimerTime%
GuiControl, Disable, %sHwndClearTimer%
}
;GUIの表示
Gui, Shutdown:Show
GuiControl, , %sHwndAfterTime%, 1
GuiControl, , %sHwndAtTime%, 1
GuiControl, , %sHwndImmediately%, 1
/**
* 実行種別ラジオボタン選択時の動作。
*/
SelectType:
;GUI変数を確定
Gui, Shutdown:Submit, NoHide
If (sImmediately)
{
;即時実行の場合、指定時刻・指定時間経過後を無効
GuiControl, Disable, %sHwndLabelSpecifiedDateTime%
GuiControl, Disable, %sHwndSpecifiedDate%
GuiControl, Disable, %sHwndSpecifiedTime%
GuiControl, Disable, %sHwndLabelAfterTime%
GuiControl, Disable, %sHwndHour%
GuiControl, Disable, %sHwndLabelHour%
GuiControl, Disable, %sHwndMin%
GuiControl, Disable, %sHwndLabelMin%
GuiControl, Disable, %sHwndSec%
GuiControl, Disable, %sHwndLabelSec%
;画面更新を停止
SetTimer, ShutdownGuiRefresh, Off
}
If (sAtTime)
{
;指定時刻に実行の場合、指定時刻を有効・指定時間経過後を無効
GuiControl, Enable, %sHwndLabelSpecifiedDateTime%
GuiControl, Enable, %sHwndSpecifiedDate%
GuiControl, Enable, %sHwndSpecifiedTime%
GuiControl, Disable, %sHwndLabelAfterTime%
GuiControl, Disable, %sHwndHour%
GuiControl, Disable, %sHwndLabelHour%
GuiControl, Disable, %sHwndMin%
GuiControl, Disable, %sHwndLabelMin%
GuiControl, Disable, %sHwndSec%
GuiControl, Disable, %sHwndLabelSec%
;画面更新を開始
SetTimer, ShutdownGuiRefresh, 0
}
If (sAfterTime)
{
;指定時間経過後に実行の場合、指定時刻を無効・指定時間経過後を有効
GuiControl, Disable, %sHwndLabelSpecifiedDateTime%
GuiControl, Disable, %sHwndSpecifiedDate%
GuiControl, Disable, %sHwndSpecifiedTime%
GuiControl, Enable, %sHwndLabelAfterTime%
GuiControl, Enable, %sHwndHour%
GuiControl, Enable, %sHwndLabelHour%
GuiControl, Enable, %sHwndMin%
GuiControl, Enable, %sHwndLabelMin%
GuiControl, Enable, %sHwndSec%
GuiControl, Enable, %sHwndLabelSec%
;画面更新を開始
SetTimer, ShutdownGuiRefresh, 0
}
Return
/**
* 指定時刻・指定時間経過入力時の動作。
*/
CalcTime:
;GUI変数を確定
Gui, Shutdown:Submit, NoHide
If (sAtTime)
{
;日付の更新を時刻に反映させる
FormatTime, vSpecifiedDate, %sSpecifiedDate%, yyyyMMdd
FormatTime, vSpecifiedTime, %sSpecifiedTime%, HHmmss
vSpecifiedTime := vSpecifiedDate . vSpecifiedTime
;GUIを更新
GuiControl, , %sHwndSpecifiedTime%, %vSpecifiedTime%
}
If (sAfterTime)
{
If (sSec >= 60 || sMin >= 60)
{
;秒または分が60の場合、繰り上げを行う
vMin := sSec // 60
vSec := sSec - (vMin * 60)
vMin := sMin + vMin
vHour := vMin // 60
vMin := vMin - (vHour * 60)
vHour := sHour + vHour
;GUIを更新
GuiControl, , %sHwndSec%, %vSec%
GuiControl, , %sHwndMin%, %vMin%
GuiControl, , %sHwndHour%, %vHour%
}
If (sSec < 0 || sMin < 0)
{
;秒または分が-1の場合、繰り下げ処理を行う
If (sSec < 0)
{
;秒が-1の場合
If (sHour == 0 && sMin == 0)
{
;時と分がどちらも0の場合、それ以上繰り下げ処理を行わない
vMin := 0
vSec := 0
}
Else
{
;それ以外の場合、分を繰り下げ処理
vMin := sMin - 1
vSec := 59
}
}
Else
{
;-1でない場合
vMin := sMin
vSec := sSec
}
If (vMin < 0)
{
;分が-1の場合
If (sHour == 0)
{
;時間が0の場合、それ以上繰り下げ処理を行わない
vHour := 0
vMin := 0
}
Else
{
;それ以外の場合、時間を繰り下げ処理
vHour := sHour - 1
vMin := 59
}
}
Else
{
;-1でない場合
vHour := sHour
}
;GUIを更新
GuiControl, , %sHwndSec%, %vSec%
GuiControl, , %sHwndMin%, %vMin%
GuiControl, , %sHwndHour%, %vHour%
}
}
;Guiの定期更新を開始
SetTimer, ShutdownGuiRefresh, 0
Return
/**
* GUIの時刻を更新する。
*/
ShutdownGuiRefresh:
;GUI変数を確定
Gui, Shutdown:Submit, NoHide
;更新間隔を設定
vTimer := 250
SetTimer, ShutdownGuiRefresh, %vTimer%
;現在日時を取得
FormatTime, vNowDateTime, , yyyyMMddHHmmss
If (sAtTime)
{
;シャットダウン時刻を計算
vTime := sSpecifiedTime
EnvSub, vTime, vNowDateTime, Seconds
If (vTime > 0)
{
;現在時刻以降を指定した場合、時間・分・秒を計算
vHour := (vTime // 60 // 60)
vMin := (vTime - (vHour * 60 * 60)) // 60
vSec := (vTime - (vHour * 60 * 60) - (vMin * 60))
}
Else
{
;現在時刻より前を指定した場合、全て0
vHour := 0
vMin := 0
vSec := 0
}
;GUIを更新
GuiControl, , %sHwndHour%, %vHour%
GuiControl, , %sHwndMin%, %vMin%
GuiControl, , %sHwndSec%, %vSec%
}
If (sAfterTime)
{
;シャットダウン時刻を計算
vSepcifiedDateTime := vNowDateTime
EnvAdd, vSepcifiedDateTime, sHour, Hours
EnvAdd, vSepcifiedDateTime, sMin, Minutes
EnvAdd, vSepcifiedDateTime, sSec, Seconds
;GUIを更新
GuiControl, , %sHwndSpecifiedDate%, %vSepcifiedDateTime%
GuiControl, , %sHwndSpecifiedTime%, %vSepcifiedDateTime%
}
Return
/**
* [実行]ボタンクリック時の動作。
*/
ShutdownExec:
;シャットダウン種別
gShutdownType := sShutdown + sReboot * 2 + sForce * 4 + sAfterProcess * 8
vShutdownType := sShutdown + sReboot * 2 == 0 ? "ログオフ" : sShutdown + sReboot * 2 == 1 ? "シャットダウン" : "再起動"
;GUI変数を確定
Gui, Shutdown:Submit, NoHide
If (sImmediately || (sHour == 0 && sMin == 0 && sSec == 0))
{
;即時実行またはシャットダウン時刻が0秒後の場合、シャットダウンを即時実行
SetTimer, StartShutdown, 0
}
Else
{
;即時実行以外の場合、シャットダウン実行確認タイマーを設定し、バルーンメッセージを表示
vTimerMSec := ((sHour * 60 * 60) + (sMin * 60) + sSec) * 1000
FormatTime, vStartTime, %sSpecifiedTime%, M月dd日 H時mm分ss秒
SetTimer, StartShutdown, %vTimerMSec%
TrayTip, ShutDown Timer, %vShutdownType%の実行を予約しました。`r`n%vStartTime%に開始されます。`r`n`r`nタイマーを解除する場合はもう一度[シャットダウンの実行]を表示し、[タイマー解除]を選択してください。, 2, 17
;現在設定中のタイマーを更新
gShutdownTimer := sSpecifiedTime
}
;GUIウィンドウを破棄
Gui, Shutdown:Destroy
Return
/**
* [タイマー解除]ボタンクリック時の動作。
*/
ClearTimer:
;シャットダウン実行確認タイマーを解除し、バルーンメッセージを表示
SetTimer, StartShutdown, Off
gShutdownTimer := ""
gShutdownType := ""
TrayTip, ShutDown Timer, `r`n設定済みのタイマーを解除しました。, 2, 17
;現在設定中のタイマーをクリアし、[タイマー解除]ボタンを非活性
GuiControl, , %sHwndTimerDate%,
GuiControl, , %sHwndTimerTime%,
GuiControl, Disable, %sHwndLabelTimer%
GuiControl, Disable, %sHwndTimerDate%
GuiControl, Disable, %sHwndTimerTime%
GuiControl, Disable, %sHwndClearTimer%
Return
/**
* [Esc][閉じる][キャンセル]ボタンクリック時の動作。
*/
ShutdownGuiEscape:
ShutdownGuiClose:
ShutdownCancel:
;メッセージ
vMessage := "シャットダウンの実行を中止しました。"
If (gShutdownTimer)
{
;現在設定中のタイマーがある場合、メッセージを追加
vMessage := vMessage . "`r`n設定済みのタイマーは有効です。"
}
;バルーンメッセージを表示
TrayTip, ShutDown Timer, %vMessage%, 2, 17
;GUIウィンドウを破棄
Gui, Shutdown:Destroy
Return
}
/**
* タイマーをオフにし、シャットダウン実行確認を表示する。
*/
StartShutdown:
;シャットダウン種別
vShutdownType := gShutdownType
vShutdownTypeName := Mod(gShutdownType, 4) == 0 ? "ログオフ" : Mod(gShutdownType, 4) == 1 ? "シャットダウン" : "再起動"
;シャットダウン実行確認タイマーを解除
SetTimer, StartShutdown, Off
gShutdownTimer := ""
gShutdownType := ""
;メッセージボックスのタイトル(グローバル変数)
gWinTitle := vShutdownTypeName . "開始"
;カウントダウン表示更新を開始
SetTimer, ShutdownCountDown, 0
;タイムアウトに10秒を設定し、メッセージボックスを表示
MsgBox, 262209, %gWinTitle%, [OK]を選択するか10秒後に%vShutdownTypeName%します。`[キャンセル]を選択すると%vShutdownTypeName%を中止します。`r`n`r`nあと !Sec! 秒, 10
IfMsgBox, Cancel
{
;[キャンセル]が押された場合、カウントダウン表示更新を解除し、グローバル変数をクリア
SetTimer, ShutdownCountDown, Off
gWinTitle := ""
gHwnd := ""
gText := ""
Return
}
;[OK]が押された/タイムアウトした場合、シャットダウン実行
;ConfirmDoTimaEnd()
Shutdown, %vShutdownType%
Return
/**
* シャットダウン実行確認をカウントダウンし、表示を更新する。
*/
ShutdownCountDown:
;通常は更新間隔を1000ミリ秒に設定
vTimer := 1000
If (gHwnd == "")
{
;ウィンドウハンドル未取得の場合、メッセージボックスのウィンドウハンドルを取得
ControlGet, sHwnd, Hwnd, ,Static2, %gWinTitle%
gHwnd := sHwnd
If (gHwnd == "")
{
;ウィンドウハンドルが取得できなかった場合、再取得
vTimer := 0
}
;カウントダウン時間を10秒に設定
vSec := 10
}
;更新の再実行を設定
SetTimer, ShutdownCountDown, %vTimer%
If (gHwnd != "")
{
;ウィンドウハンドル取得済みの場合
If (gText == "")
{
;メッセージボックスの表示メッセージ未取得の場合、メッセージを取得してグローバル変数に格納する
ControlGetText, vText, Static2, A
gText := vText
}
;表示用テキストをカウントダウン後の内容で更新
vSetText := gText
StringReplace, vSetText, vSetText, !Sec!, %vSec%, All
;メッセージボックスのテキストを更新
ControlSetText, , %vSetText%, ahk_id %gHwnd%
;カウントダウン時間をマイナス1秒
vSec -= 1
}
Return
/**
* シャットダウン実行確認
*
* @hotkey [Win]+[Esc]
* @target デフォルト
*/
# Esc::
IfWinNotExist, シャットダウンの実行 ahk_exe AutoHotkey.exe
{
ConfirmShutdown()
}
Else
{
WinActivate
}
Return