自習室

こもります

長期展示や実験の運用のため Windows8.1を定期的に自動再起動させる

はじめに

f:id:AMANE:20150202202006j:plain

展示や実験の運用で、定期的にPCを休ませたい、自動的に再起動してリフレッシュした後・展示・実験を再開したい、というニーズがあると思います。ありました。そのための手法を考えてみました。

修正

投稿当初、以下の様に書いていたのですが

Microsoft アカウント を利用しているとパスワード解除ができず、PCの再起動をしたとしてもログイン前で止まってしまいます。MSアカウント を利用されている方は、以下の手順でローカルアカウントログインに変更します。

その後調べていたら、MSアカウントでもパスワード無しで起動時ログイン出来ることがわかりました。その点について修正しています。

前提

- Windows8.1
- Microsoft アカウントを利用したまま、パスワードを不要にする **または**
- Microsoft アカウントでのログインは利用せず、マシンのローカルアカウントログインとする
- その上で、パスワードを解除してマシンを運用する
- BIOSに、Auto Power On 的な機能がないものとする

Windows 8.1 としましたが、おそらくwindows7,8 でも同様に可能だと思います。

Auto Power On があれば

完全にシャットダウンした状態からでもマザーボードの持っているタイマーで起動ができるので、本記事で説明するような 必要時間休止→復帰→リブート というプロセスを通る必要がなくなります。

本記事では、Auto Power On的な機能がない場合にどうするか、について説明していきます。

Auto Power On については下記記事を参考にされてください

MSアカウント でのログインのまま、起動時のパスワード入力を不要にする

下記サイトの方法で可能です

(または)ローカルアカウントにし、パスワードを解除する

Microsoft アカウント を利用しているとパスワード解除ができず、PCの再起動をしたとしてもログイン前で止まってしまいます。MS ID を利用されている方は、以下の手順でローカルアカウントログインに変更します。

ローカルアカウントを使用すると、パスワードをそもそも設定しないことが出来ます。

この工程の一番最後で、パスワードを入れて確認するところがありますが、ここを空白のまま「次へ」進むと、パスワードが解除された状態でローカルアカウントに切り替わります。

ちなみに、MSアカウント時代のデータが消えたりはしないのでご安心ください

工程

全容はこんな感じ

1. 展示・実験の終了時刻になったら、動いていたプロセスを殺して、PCをシャットダウンできる状況にする
2. ハイバネーション(休止)状態にする
3. 展示・実験の開始時刻の少し前に、タスクスケジューラの機能でハイバネーション(休止)から復帰する
4. 再起動する
5. 展示・実験に必要なプログラムをスクリプトで起動する

先述の通り、Auto Power On が出来ないためシャットダウンはせず、しかしハイバネーションさせることで極力PCを休ませたのちリフレッシュのために再起動する、という作戦となっています。

一個ずつ見ていきます

1. 動いていたプロセスを殺す + 2. ハイバネーション

バッチファイル作成

以下のようなバッチファイルを作成して適当な場所に置いておきます

rem
rem goToSleep.bat
rem

echo "kill all apps and go to Hibernation"

taskkill /im "iexplore.exe" /f

timeout /T 10

taskkill /im "notepad++.exe"

timeout /T 20

rundll32.exe PowrProf.dll,SetSuspendState

ここでは、 IEと "notepad++.exe" というアプリが仮に展示で使われていると仮定して、それを殺し、20秒待った後、ハイバネーションに入る、というバッチとなっています。

ハイバネーションは、setsuspendstate というWindowsAPIを使うことで実現しています。

rundll32.exe の罠

このStackoverflow のスレッドでは、 rundll32.exe PowrProf.dll,SetSuspendState 0,1,0 でスリープする、と言っていますが、これは間違いなようです。私も数パタン試してみましたが、最後のbool三つの「引数のような指定」はおそらく機能しておらず、すべてハイバネーションしています。APIのデフォルトの動作なのでしょうか。

この状態でも今回の目的は達成できているとも言えるのですが、もし何かしらの理由でハイバネーションできない/したくない場合は、正しくスリープのAPIを呼ぶ必要があります。プログラムからスリープを呼ぶ方法は、以下のページ様の手法で確認が出来ました。

これをちょっとカスタムして、以下のコードでプロジェクトを作って、exe をはき出しておきます。

// これを、 GoToSleep.exe としてビルド

#include <Windows.h>
#include <powrprof.h>
#pragma comment(lib, "powrprof.lib")

int main()
{
    SetSuspendState(FALSE, FALSE, FALSE);
    // 第1引数がFALSEだとスリープ、TRUEだと休止(hibernation)
    return 0;
}

その上で、バッチファイルを書き換えます

rem rundll32.exe PowrProf.dll,SetSuspendState
cd <PATH_TO_EXE>
start GoToSleep.exe

これで正しくスリープ / 休止が出来ます。

タスクスケジューラに登録
  • コントロールパネル > システムとセキュリティ > 管理ツール > タスクスケジューラ でタスクスケジューラを開きます
  • 基本タスクの作成 をクリックすると、タスク作成のウィザードが始まり、埋めていくことでタスクを登録できます。
  • 名前を適当につけます。 goToSleep とか
  • PCをハイバネート/スリープ させたい周期を考えてトリガーに登録します (たとえば、「毎日、20:30」 など
  • 操作として、先ほど作成したバッチを登録します

このスクリプトについては、タスクのオプションをいじる必要はありません

3. ハイバネーションから復帰 + 4. 再起動

バッチファイル作成

Windows 標準のタスクスケジューラの機能で、ハイバネーション or スリープ から復帰することができます。

以下のようなバッチファイルを作成して、適当な場所に置いておきます

rem
rem wakeFromSleepAndReboot.bat
rem

echo "wake from sleep and reboot"

timeout /T 20

shutdown -r -t 10

ここでは、20秒待ったのちリブートする、というスクリプトになっています。

タスクスケジューラに登録

今回、ハイバネーション/スリープからの復帰は、タスクスケジューラの機能を用いて行います。まず一個前と同様に作成したバッチをタスクスケジューラに登録します。

その後、登録したタスクのプロパティを開き 条件 タブ中の 「タスクを実行するためにスリープを解除する」 にチェックを入れます。

f:id:AMANE:20150202201830p:plain

これで、ハイバネーション/スリープ中であっても、登録したバッチが実行されるようになります。

このあたりについては、こちらのサイトで紹介されていました。

5. 必要なプログラムの起動

バッチファイル作成

複数のプログラムを順に起動したい場合も多いと思うので、これもバッチを作ります。

例として、notepad++ と IE を起動します。(意味はとくにありません(>_<))

rem
rem launchApps.bat
rem

echo "launch apps"

cd "C:\Program Files (x86)\Notepad++"
start notepad++.exe

timeout /T 10

start iexplore.exe

exit

notepad++ を起動した後、10秒待って、Internet Explorer を立ち上げます

タスクスケジューラに登録

ここでは上二つのバッチとは異なり、時刻指定ではなく、スタートアップを引き金としてアプリを立ち上げる指定にしてみます。起動からPCが色々立ち上げたり、ネットワークがつながって落ち着くまでの時間を多少取った方が良いかとも思うからです。

「基本タスクの作成」のウィザードで、トリガー を「コンピュータの起動時」にします。これでも十分かもしれませんが、更に少し余裕を持たせるために、開始を遅延させます。

  • タスクスケジューラの一覧から今登録したタスクのプロパティを開く
  • トリガースタートアップ時 を編集します。
  • 遅延時間を指定する にチェックを入れて、適当に時間を設定します。たとえば起動後1分。

f:id:AMANE:20150202195533p:plain

これで、上記のバッチは起動後1分で実行されることになります。

完成!

以上で、定期的に再起動する仕組みができました。ハイバネーションの設定周りで、PCごとに差があるかもしれません。その辺りは各自柔軟に対処、と言うことで。

Sleep / Standby / Suspend / Hibernation / Hybrid Sleep について

今回、setsuspendstate の挙動で結構はまっていろいろ調べたところ、日本語と英語の間、また、プログラマWindowsの一般ユーザ の間で、スリープや休止に関する言葉の使い方がそれぞれ異なることがわかりました。ここに整理してまとめておきます。

参照

Sleep == Standby == (hibernationでは無い)Suspend == スリープ、スタンバイ

メモリ上にOSの状態を残し、メモリにのみ通電を続けるもの。直ぐ起動できるがやや電気を食う。

Hibernation な suspend == 休止

HDD/SSD にOSの状態を保存し、いったんシステム全体の電源を落とす物。やや起動に時間がかかるが、シャットダウン時と同様に電気を使わなくなる

Hybrid Sleep == ハイブリッドスリープ

上の二つの合わせ技。通常はスリープ的に寝ていて直ぐ起動できる状態であるが、電池が切れそうになるとHibernation状態に移行する

初め、Suspend == 休止 だと思い込んでいて混乱しました。

さいごに

もしかすると似たような事をする為のユーティリティソフトもあるかもしれませんが、あまり調べていません。もし良いものをご存じの方がいらっしゃいましたら、教えていただけると嬉しいです。