簡単WMメッセージ送信
とりあえず「コンソールアプリ」を作成。
機能は「ウィンドウの存在確認」と「ウィンドウにメッセージの送信」の2つです。
どんな操作が可能かは送るメッセージによります。
メッセージとはマイクロソフト社が予め決めてある物なので基本的にどんなアプリでも
そのメッセージを処理する機能が付いていれば操作可能です。
※2015/12 MicrosoftEdgeとgoogle Chromeの操作サンプルを付けてみました。
※2017/4/29 ボタンを押す機能とマウス移動をくみあわせる。
2017/4/29更新
戻り値: バッチファイルにて%ERRORLEVEL%にて取得可能
0 または 検索一致数 または プロセスID
32/64ビット:wmsmsg.exe.ZIPファイル置き場(SkyDrive)
使用例 (解説は例が終わってからにします)
※実際の使い方は次とその次のページにもあります。
注:ブログの投稿仕様により一部半角クォーテーション(”)が全角に変換表示されています
―――――――――――――――――――――――――――――――――――――――――――
「インターネットエクスプローラ(iexplore.exe)、メモ帳(notepad.exe)、Firefoxブラウザを操作してみます」
もしバッチファイルの中でコマンドを2行に別けて書く時は行末に”^”を付けて下さい
ウィンドウ終了 (ALT+F4)
wmsmsg64.exe /NOALL /FM:iexplore.exe /DISP:1 /WM:0x112 /WP:0xF060
ウィンドウ終了 (標準終了メッセージ)
wmsmsg64.exe /NOALL /FM:iexplore.exe /DISP:1 /WM:0x10
文字コード送信 (メモ帳に文字'A'を送る)
wmsmsg64.exe /and /child /fm:notepad.exe /fc:Edit /noall /disp:1 ^
/wm:0x102 /wp:0x41 /post
キーコード表 Virtual-Key Codes
WM_SYSCOMMAND Message (Windows)
ウィンドウのタイトル文字を変更する
wmsmsg64.exe /noall /fm:notepad.exe /wm:0xC /lp:タイトル変更した
子ウィンドウに送るには例えばこんな感じでIEの"YouTube"のタブだけ全部閉じる
wmsmsg64.exe /Child /NoAll /And /FM:iexplore.exe /disp:1 ^
/FT:"YouTube - " /FC:TabWindowClass /Post /WM:0x10
※5分毎にIEの特定タブをリロード(F5キー)させるバッチ
@echo off
:IETabReDraw
wmsmsg64.exe /child /and /disp:1 /FM:iexplore.exe /FT:"Yahoo! JAPAN" ^
/FC:TabWindowClass /Post /Wm:0x100 /Wp:0x74 /Wsec:300
goto IETabReDraw
ウィンドウを前面に持って来る(フォーカスあり)
これがやってみると単純なようで結構難しかったので専用コマンド(/WAct)
wmsmsg64 /noall /fm:iexplore.exe /wact /disp:1
ウィンドウを前面に固定(フォーカスなし)
FLASHコンテンツ等を全画面表示時にサイドバーガジェットを見えるように前面表示(/WTop:)
常に前面 wmsmsg64 /and /fm:sidebar.exe /fc:BasicWindow /disp:0 /wtop:2
普通に戻す wmsmsg64 /and /fm:sidebar.exe /fc:BasicWindow /disp:0 /wtop:3
ウィンドウ スタイルの値表示
wmsmsg64 /noall /fm:iexplore.exe /debug /disp:1
Winアプリを起動してウィンドウ表示を待ってから各種操作するバッチサンプル
※アプリのショートカットを起動、ウィンドウタイトルの表示をループ中で待ち、
最小化・最大化ボタンを無効にするメッセージを送信している
@echo off
start "" "C:\Users\Public\Desktop\Mozilla Firefox.lnk"
:WAITLOOP
wmsmsg64 /disp:1 /noall /and /ft:"- Mozilla Firefox" /fm:firefox.exe /wsec:1
if %errorlevel% equ 0 (goto WAITLOOP) else (goto CHANGESTYLE)
:CHANGESTYLE
wmsmsg64 /disp:1 /noall /and /ft:"- Mozilla Firefox" /fm:firefox.exe ^
/wm:0x7c /wp:-16 /lp:0x16CC0000 /wact
特定のエディットBOXに値を設定する(文字として555という数値を入力)
wmsmsg64 /child /and /fm:実行ファイル名.exe /wst:"親タイトル名" /fc:Edit ^
/fid:EditBoxのID /wm:0x0c /lp:555 /disp:1 /noall /noh
ダイアログのOKボタンに直接リターンキーを送る
wmsmsg64 /child /and /wst:"親タイトル名" /ft:OK ^
/wm:0x100 /wp:0x0d /Post /disp:1 /noall /noh
※OKボタンのタイトル名が"OK"であると仮定、別文字に変更されていれば当然その文字を指定。
※/postを使わないと無反応なウィンドウがあるので注意
※OKボタンを押すには別の方法もあります、頁下の応用で使ってます
※以下,上から 移動・サイズ変更・使用不可/可・非表示/再表示 です
Firefoxブラウザを操作しています
WM_MOVE:位置変更(X=10、Y=20)
wmsmsg64 /noall /fm:firefox.exe /disp:1 /wm:0x0003 /lpLo:10 /lpHi:20
WM_SIZE: サイズ変更(800X600)
wmsmsg64 /noall /fm:firefox.exe /disp:1 /wm:0x0005 /lpLo:800 /lpHi:600
WM_ENABLE:ウィンドウ使用不可
wmsmsg64 /noall /fm:firefox.exe /disp:1 /wm:0x000A /wp:0
WM_ENABLE:ウィンドウ使用可
wmsmsg64 /noall /fm:firefox.exe /disp:1 /wm:0x000A /wp:1
WM_SHOWWINDOW:ウィンドウ非表示
wmsmsg64 /noall /fm:firefox.exe /disp:1 /wm:0x0018 /wp:0
※説
/wm:の値定義 WM_SHOWWINDOW 0x0018
/wp:の値は
SW_HIDE 0
SW_SHOWNORMAL 1
SW_SHOWMINIMIZED 2
SW_SHOWMAXIMIZED 3
SW_SHOWNOACTIVATE 4
SW_SHOW 5
SW_MINIMIZE 6
SW_SHOWMINNOACTIVE 7
SW_SHOWNA 8
SW_RESTORE 9
SW_SHOWDEFAULT 10
SW_FORCEMINIMIZE 11
なので /wp:6 (か7)とすると最小化します
WM_SHOWWINDOW:非表示ウィンドウの再表示
wmsmsg64 /noi /not /nom /and /fc:MozillaWindowClass ^
/fm:firefox.exe /disp:1 /wm:0x0018 /wp:8
※追加条件の/and /fc:MozillaWindowClass を付けないと本来非表示の物まで表示され変になる
システムメニューの×ボタンの使用不可
※見た目のみ:マウスで×ボタンは押せなくなりますがAlt+F4は効きます
「/lphi:6」はシステムメニューの上からの番目数
※ゼロから数えてセパレータも含め、通常は6番目です。
wmsmsg64 /noall /fm:iexplore.exe /wm:0x7C /disp:1 /wp:-30 /lplo:1 /lphi:6
システムメニューの初期化 (すべて標準状態に戻す)
wmsmsg64 /noall /fm:iexplore.exe /wm:0x7C /disp:1 /wp:-30 /lplo:0
マウスカーソル移動 (「「メッセージを送った」」ウィンドウにカーソルを移動)
wmsmsg64 /noall /fm:firefox.exe /disp:1 /wm:0x3 /lpLo:10 /lpHi:20 /mouse
wmsmsg64 /noall /fm:firefox.exe /disp:1 /wm:0x18 /wp:1 /mouse
マウスカーソル移動 (ただの移動:左上)
wmsmsg64 /noall /nohr /fm:0x0000 /mouse >nul
マウスカーソル移動 (ただの移動:指定位置)
wmsmsg64 /noall /nohr /fm:0x0000 /mouse /mx:100 /my:200 >nul
プロセスIDでの検索
wmsmsg64 /noall /noh /disp:1 /fpid:4168
プロセスIDの取得
wmsmsg64 /noall /nohr /fm:iexplore.exe /disp:1 /pid
@if %errorlevel% equ 0 (@echo 存在せず) else (@echo お探しのIDは %errorlevel% です)
UACが有効なPCでこの種のバッチファイルやVBスクリプトをタスクスケジューラで
定期的に起動する場合は 「最上位の特権で実行する」 のチェックが必要です。
よくやるミス:
オプションの /and /disp:1 /noall を付け忘れてリストがだらだら出たり、検索一致しない。
”管理者でコマンドプロンプト” を開いて「wmsmsg32.exe」か「wmsmsg64.exe」と打ちます。
非表示とタイトルの無いウィンドウの”Explorer.EXE”や”IME”が沢山居るので除外します。
「wmsmsg64.exe /NoV /NoT /Child」これで現在のPCの状態がまともに見れます。
以下に「インターネットエクスプローラ」の情報を出したときで解説します。
説明用に「インターネットエクスプローラ」をURL指定してコマンドラインから起動します。
「”C:\Program Files (x86)\Internet Explorer\iexplore.exe” https://kawashima38.wordpress.com」
そして「wmsmsg64 /noall /child /fm:iexplore.exe /disp:2」と打ちます。
黄色で始まる行から
1行目:「ウィンドウを識別する英数値(ハンドル)」・「プロセスID」・「タイトル名」の3つが表示されています。
2行目(>>):アプリケーションの「実行モジュール名」です。
3行目(::):アプリ起動時に指定された「コマンドラインパラメータ」の文字列です。
4行目(>:):ウィンドウの「クラス名」、OSの内部的な名前と思って下さい。
5行目以降(-:):内包する子ウィンドウの「クラス名」・「コントロールID」・「テキスト」です。
で、検索オプションを使って以上の情報から一致する目的のウィンドウを検索します。
例えば:「タブ」を操作するには子ウィンドウのクラス名検索の「/AND /FC:TabWindowClass」を
を追加指定すれば「目的のタブ」にメッセージを送れます。
なぜ/FC:TabWindowClassだと判るのか?と言うとクラス名は素直に読めば理解できる名前が
付いている事とそのタイトルテキストが「@ぐるぐる~」と付いてるので簡単に類推できるからです。
またアプリがどんな状態で起動されたかを調べるには「/FA:」で「コマンドラインパラメータ」を
検索条件にすればだいたいの事は判断できます。
オプション | 説明 |
---|---|
/NOV | 非表示ウィンドウはリストに出さない |
/NOT | ウィンドウタイトルが空白ならリストに出さない |
/NOM | 実行ファイル名を取得不能なウィンドウをリストに出さない |
/NOI | IMEウィンドウをリストに出さない ウィンドウタイトルが "MSCTFIME UI" ウィンドウタイトルが "Default IME" ウィンドウタイトルが "imejpstmain" |
/NOALL | 全部指定 (/NoV, /NoT, /NoM, /NoI) |
/NOH | ヘッダー行を出力しない |
/NOR | 最後の結果行を出力しない |
/NOHR | ヘッダーと結果行を出力しない(/NoH, /NoR) |
/debug | デバッグ用(表示が少し増える) |
/POST | PostMessageを使いアプリの返信メッセージを待たないで復帰する、通常はSendMessage ※例外でWM_STYLE~のメッセージのみ"SetWindowLong"を使用 |
/CHILD | 子ウィンドウも取得します(クラス名・ID・ウィンドウテキスト) IDとウィンドウテキストは無い場合もあります |
/PID | 検索条件と最後に一致したウィンドウのプロセスIDを戻り値として返します |
/PARENT | 子ウィンドウを検索した場合にメッセージの送り先を子ウィンドウではなく、その親ウィンドウに対して送信します 正確には階層上の直前の親ではなくプロセスのトップウィンドウです |
/AND | 複数の検索条件をAND(全条件一致)で処理します。通常はOR(個別一致)処理 |
/FM: | 実行ファイル名を検索します。 ファイル名でもフルパス名の一部でもいいです 空白を含む場合は””でくくります 一致するものがあれば戻り値として「一致数」を返します デスクトップシェルにメッセージを送る場合 0x0000 を指定 全ウィンドウにブロードキャストで送る場合 0xFFFF を指定 |
/FT: | ウィンドウタイトル名を検索します タイトル名全部ではなく一部でもいいです 空白を含む場合は””でくくります 一致するものがあれば戻り値として「一致数」を返します /Child指定時は子ウィンドウタイトル名も検索対象 |
/WST: | 子ウィンドウを検索する場合に、複数プロセスで重複一致を避ける為にその親ウィンドウのタイトル名を指定可能です (必須ではありません) 空白を含む場合は””でくくります /Child指定時のみ有効、それ以外は無視されます |
/FC: | クラス名を検索します クラス名全部ではなく一部でもいいです 空白を含む場合は””でくくります 一致するものがあれば戻り値として「一致数」を返します /Child指定時は子ウィンドウクラス名も検索対象 |
/FPID: |
プロセスIDを検索します 一致するものがあれば戻り値として「一致数」を返します |
/FA: |
コマンドラインパラメータを検索します パラメータ全部ではなく一部でもいいです 空白を含む場合は””でくくります 一致するものがあれば戻り値として「一致数」を返します |
/FID: | 子ウィンドウのコントロールIDを検索します リストでは[数値]で表示されています(存在すれば) (ボタン・エディット・リスト・コンボ等の内部番号です) 同じクラス名(コントロール)を区別するのに利用可能です そのアプリが更新されない限り、またはコントロールが動的に生成されていなければ何度起動されても同じ番号のはずです 10進数で指定 一致するものがあれば戻り値として「一致数」を返します /Child指定時のみ有効、それ以外は無視されます |
/WM: | 検索で一致したウィンドウに送るメッセージを指定 0xで始まる16進、または10進を指定 送るメッセージが無ければこのオプションは必要無し ※以下の2つのメッセージだけ特別に「/LP:」1つに値指定で処理します。 (別ページの使用例を見ると判ります) WM_STYLECHANGING 0x007C WM_STYLECHANGED 0x007D |
/WP: |
メッセージと一緒に送るWPARAMを指定 0xで始まる16進、または10進を指定 送るWPARAMが無ければこのオプションは必要無し |
/LP: | メッセージと一緒に送るLPARAMを指定 0xで始まる16進、または「文字列」を指定 送るLPARAMが無ければこのオプションは必要無し キャストしてるだけなので複雑なものは指定不能 空白を含む場合は””でくくります |
/WPLO: | WPARAMのLOWORDの値を指定 0xで始まる16進、または10進を指定 これが指定されると/WP:の方は無視される 設定する値が無ければこのオプションは必要無し |
/WPHI: | WPARAMのHIWORDの値を指定 0xで始まる16進、または10進を指定 これが指定されると/WP:の方は無視される 設定する値が無ければこのオプションは必要無し |
/LPLO: | LPARAMのLOWORDの値を指定 0xで始まる16進、または10進を指定 これが指定されると/LP:の方は無視される 設定する値が無ければこのオプションは必要無し |
/LPHI: | LPARAMのHIWORDの値を指定 0xで始まる16進、または10進を指定 これが指定されると/LP:の方は無視される 設定する値が無ければこのオプションは必要無し |
/DISP: | リスト表示するレベル 0 画面表示なし 1 検索一致したウィンドウ 2 検索一致したプロセスが含むウィンドウ 3 全部表示 このオプション無し=全部表示 |
/WACT | 検索一致したウィンドウをアクティブにし、前面に表示します |
/WSEC: | ウィンドウ検索を実行する前にウェイトを入れます 秒数を指定 |
/WTOP: | 検索一致したウィンドウの前面表示管理を設定します 1 前面に移動 2 常に前面表示 3 常に前面を解除 |
/MOUSE | 検索一致したウィンドウの中央にマウスカーソルを合わせます |
/MX: | (検索一致と無関係に)マウスカーソル移動。横位置を指定、10進数、/MOUSE指定が必要 |
/MY: | (検索一致と無関係に)マウスカーソル移動。縦位置を指定、10進数、/MOUSE指定が必要 |
/HELP または /? | 簡単なパラメータの説明を表示 |
/BDWN: | 検索一致したウィンドウにマウスカーソルを合わせてボタンを押したメッセージ(WM_xBUTTONDOWNとWM_xBUTTONUP)を送信します 1 左ボタン 2 右ボタン 3 中央ボタン ※/cmx:、/cmy:と組み合わせて目的のウィンドウの任意座標でボタンを押せる、組み合わせない場合はウィンドウの中央で押す |
/CMX: | 検索一致したウィンドウのクライアント座標でマウスカーソルを移動する横位置を指定、10進数 (/MOUSE不要) |
/CMY: | 検索一致したウィンドウのクライアント座標でマウスカーソルを移動する縦位置を指定、10進数 (/MOUSE不要) |
オプションは基本的に独立しているのでただし書きが無ければ任意に組み合わせ指定が可能
色: 検索一致=黄色、 実行ファイル名が取得出来ない等エラー=青、 他=白
検索で複数のウィンドウが一致すると一致したウィンドウ(黄色)全部にメッセージが送られます。
※応用してみる
「wmsmsg64 /fm:0x0000 /wm:0x10 /post」とデスクトップシェルに対して終了を送信すると
以下の様な画面が出てくる。 ここで矢印キー上を送れば「休止」「スリープ」が選べて
後はリターンキーを送れば良さそうに見えるのですが、残念ながら上手く動かない。
ドロップダウンリスト用のメッセージを送らないと駄目かもしれない、調査が面倒だ。
しかもこの画面を調べようにもフォーカスが外れると自動で閉じてしまい調べられない
32bitOSなら wmsmsg32 /fm:0x0000
その後少し実験した結果、成功してスリープしました。
wmsmsg64 /FM:0x0000 /WM:0x10 /Post /Disp:0
wmsmsg64 /Child /WST:"Windows のシャットダウン" /And /FC:ComboBox ^
/FID:2001 /WM:0x014E /WP:3 /NoAll /WAct /WSec:3 /Disp:1
wmsmsg64 /FT:"Windows のシャットダウン" /Post /WM:0x0111 /WP:1 /NoAll /Wsec:2 /Disp:1
上の3行をバッチファイルに書いて呼び出すとスリープします。
2行目:/WM:0x014E はコンボボックス選択のCB_SETCURSELメッセージ
2行目:/WP:3 はコンボボックスの選択場所が上から4番目(0から数えて)
2行目:/FID:2001 はコンボボックスが非表示含めて2つあるのでIDで区別してます
3行目:/WM:0x0111 は処理するWM_COMMANDを送ったので頼むって意味です
3行目:/WP:1 は頼む内容がダイアログ上のOKボタン(IDOK=1)だよって事です
こんな感じです。
※バージョンやエディションが違う場合に「IDが2001」かは、1回表示させてみないとわかりません。
3行目は単にリターンキーでもいいかもしれない
wmsmsg64 /FT:"Windows のシャットダウン" /Post /WM:0x100 /WP:0x0d /NoAll /Disp:1
2行目の以下の部分も要らないといえばいらない (あった方が判りやすい)
/And /FC:ComboBox
※ このプログラムはウィンドウの存在をチェックしたり、該当するウィンドウ
があればメッセージを送るのが目的なので、
元々ウィンドウを持たない様なプロセスは一覧に出ないかと思われます。
※ .NETは不要。
※ 引数の大文字小文字区別なし(内部ではすべて小文字にして比較)。
※ 引数のチェックは無し(数値部分に文字指定”/WP:あいう”等はX)。
※ 使う上で一番ネックになる使用可能なメッセージの定義は
“WinUser.h” とかでWeb検索するとかしてください。
※ UACが有効な場合はコマンドプロンプトは管理者として実行する必要がある場合もあります。
※ 64ビットOS上で32ビット版のwmsmsg32を使うとWoWを介しているので
64ビットアプリの一部情報は取得出来ません。
以下のように水色でエラー表示になります(error window = ** )。
[おわり]
投稿日: 2011/07/15 | カテゴリー: ツール、アプリ, Windows OS | パーマリンク 1件のコメント.
バッチでpostmessageをしたくて検索していたらここに辿り着きました。
Skydriveにあるファイルをダウンロードできませんでした。
もし連絡とれるのでしたら使ってみたいのでお願いします。