読者です 読者をやめる 読者になる 読者になる
スポンサーリンク

画面をコマンドラインからキャプチャする方法 (WSHバッチでPrintScreen)



PCの画面のスクリーンショット作成のために,通常は

  • PrtScrキーを押して
  • 画像編集ソフトを起動し
  • ペーストして
  • 画像をファイルに保存し
  • 画像編集ソフトを閉じる

といった手順を踏む。


この面倒な作業は,WSHのスクリプトで自動実行できる。




JScript / VBScript では Sendkeys メソッドを使ってキー操作をする。

ところが残念なことにPrtScrキーは押せない


ためしに下記のコードを実行してみよう。

var ws = WScript.CreateObject("WScript.Shell");
ws.SendKeys( "{PRTSC}" );

適当な名前.js で保存してダブルクリックで実行したのち,画像編集ソフト上でペーストしようとしても,何も起こらない。

キャプチャできていないのだ。



しかしかわりに,WSHからExcelのマクロを呼び出すという手がある。

画面全体やアクティブウィンドウのスナップショットを取得する。
http://scripting.cocolog-nifty.com/blog/2007/07/post_d000.html


WScript.ShellのSendKeys()では、PrintScreenキーを送ることができません。


Excelには、DLL関数を呼び出すCALLマクロと、マクロを呼び出すExecuteExcel4Macroメソッドがあります。
これを利用して、スクリプトからWin32APIのkeybd_event()を呼び出します。

画面全体のスナップショットを取得します。

こちらはちゃんとキャプチャされる。

そして,結果をクリップボードに格納するだけでなく,ビットマップファイルとして保存する所までやらせてしまいたい。


そのためにはキャプチャしたあとで

  • 「ペイント」を自動で起動し,
  • Ctrl + V キーを自動で押させてペーストし,
  • Ctrl + S キーを自動で押させて保存し,
  • ALT + F4 キーを自動で押させてペイントを終了

という流れにすればよい。


下記のスクリプトを 適当な名前.js で保存・実行。

// 画面キャプチャ(Excelが必要)
var excel = WScript.CreateObject("Excel.Application");
excel.ExecuteExcel4Macro( "CALL(\"user32\",\"keybd_event\",\"JJJJJ\",44,121,1,0)" );
excel.ExecuteExcel4Macro( "CALL(\"user32\",\"keybd_event\",\"JJJJJ\",44,121,3,0)" );

// 現在アクティブなウィンドウを最小化
// 
//   ※エクスプローラ上でこのスクリプトを
//     ダブルクリック等により起動した場合,
//     単にペイントをAppActivateするだけだと,
//     エクスプローラがアクティブなままになる。
//     ペイントをアクティブにするためには,このように最小化して
//     エクスプローラからフォーカスを外す。
//
var ws = WScript.CreateObject("WScript.Shell");
ws.SendKeys( "% n" );    


// 空画像を作成
var bmpname = "clip" + (new Date()).getTime() + ".bmp";
var out = WScript.CreateObject("ADODB.Stream");
out.Type = 1; // バイナリモードで書き込み
out.Open();
out.SaveToFile( bmpname, 2 ); // 上書き保存
out.Close();


// MSペイントを起動・最大化 http://msdn.microsoft.com/ja-jp/library/cc364421.aspx
var mspaint = ws.Run("mspaint.exe " + bmpname, 3);
WScript.Sleep( 1000 );
var ret = ws.AppActivate( mspaint );

// 画像を保存
ws.SendKeys( "^v" );    // ペースト
ws.SendKeys( "^s" );    // 保存
ws.SendKeys( "%{F4}" ); // 終了

// さっき最小化したアプリケーションを復元
ws.SendKeys( "%+{TAB}" );

実行環境には Excel がインストールされている必要がある。

実行すると,「clip(現在のUNIX時刻).bmp」という名前でスクリーンショットが保存される。
(実行中はマウスを動かしたりしてはいけない。)




画面キャプチャ用には専用のフリーソフトも多数存在するが,このように

  • エディタでバッチを書くだけで
  • ダブルクリック一発で

済む,というのは便利だ。


% や ^ など,Sendkeysで特殊キーを送信する際の記法は下記を参照。

運用 Windows管理者のためのWindows Script Host入門 WshShellオブジェクトの詳細(1)
4.キー・ストロークの送信とプログラムのアクティベーション
http://www.atmarkit.co.jp/fwin2k/operation/wsh05/wsh05_04.html


また,もしデスクトップにこのバッチを置いてよく使うような場合は,下記のコードでよいだろう。(ウィンドウの切り替えが不要)

var excel = WScript.CreateObject("Excel.Application");
excel.ExecuteExcel4Macro( "CALL(\"user32\",\"keybd_event\",\"JJJJJ\",44,121,1,0)" );
excel.ExecuteExcel4Macro( "CALL(\"user32\",\"keybd_event\",\"JJJJJ\",44,121,3,0)" );

var ws = WScript.CreateObject("WScript.Shell");
ws.SendKeys( "% n" );    

var bmpname = "clip" + (new Date()).getTime() + ".bmp";
var out = WScript.CreateObject("ADODB.Stream");
out.Type = 1;
out.Open();
out.SaveToFile( bmpname, 2 );
out.Close();

var mspaint = ws.Run("mspaint.exe " + bmpname, 3);
WScript.Sleep( 1000 );
var ret = ws.AppActivate( mspaint );

ws.SendKeys( "^v" );
ws.SendKeys( "^s" );

AppActivateに関する補足

ところで上記のコードでは,コメントにある通り,ペイントをアクティブにするためにちょっとした余分な操作を行なっている。


アプリケーションにキー操作のメッセージを送るためには,そのアプリケーションがアクティブになっている必要がある。

そして,アプリケーションのウィンドウをアクティブにするためには,WSHでは AppActivate を使う。


しかしこの AppActivate は,「ダブルクリック等でスクリプトを起動」という状況ではエクスプローラにフォーカスが行ってしまい,失敗する。
(ファイルを選択してEnterキーを押下した場合も同じ。)


この問題を回避するために,上記のコードでは

  • 始めに,Alt + Space + N キーを自動で押させて最小化
  • 最後に,Alt + Shift + Tab キーを自動で押させて,最後に最小化したアプリケーションを復元

という操作を付加している。


Windowsでは,Alt + Tab キーを押すことでアクティブなアプリケーションの切り替えができる。

この切り替えの順番上では,最小化されたアプリケーションは一番最後に来る。

なので,Shiftを押しながら逆順に切り替えることで,先ほどの画面と同じ状態を復元できるのだ。



追記

下記もご覧ください。

画面のスクリーンショットを,Excelブック内に自動的に保存するバッチ
http://d.hatena.ne.jp/language_and_engineering/20100425/p1