- ベストアンサー
スクリプトで通知領域にあるソフトを実行する方法
- Windows XP環境でのスクリプトを使用した通知領域にあるソフトの実行方法について教えてください。
- タスクバーの右側にある通知領域に表示されるソフトを、Windows Scriptを使用して実行したいと考えています。
- 具体的な操作例として、ソフト「sample.exe」を右クリックメニューまたはショートカットキーで実行する方法を知りたいです。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
最終的にMissing0001さんのやりたいことが実現できるかわかりませんが、【C#プログラムで】秀丸エディタの通知領域のアイコンをクリックし、ファイルを開くダイアログを表示することに成功しましたので、ご報告します。 通知領域のアイコンをクリックするのはWSH(Windows Script Host)では困難だと思います。そもそもWindows標準のスクリプトの機能ではアイコンを右クリックすることすらできません。 ご質問を見て最初に思いついたのは、アイコンをクリックするために、WSHで呼び出せるフリーソフトを使うことでした。 http://www.autoitscript.com/autoit3/ AutoItというフリーソフトをインストールすると下のようなWSH JScriptを書けます(もちろんVBScriptでも書けます)。 ----- var Aix = WScript.CreateObject("AutoItX3.Control"); var Wsh = WScript.CreateObject("WScript.Shell"); Aix.MouseClick ("Left", 1294, 880); // アイコン座標決め打ち WScript.Sleep(100); Wsh.SendKeys("O"); ----- しかしご覧のとおり、AutoItでも通知領域の中を検索することはできないので、アイコン座標決め打ちです。使えないこともないですが…。 そこでスクリプトはあきらめ、.NET Framework 3.5上でWindowsオートメーションAPIを使ったC#プログラムを書いてみました。これなら通知領域の中も検索できます。 WindowsオートメーションAPIはWindowsXP、Vistaの場合、重要度推奨の更新プログラムKB971513になっていて、意図して組み込む必要があります。なおVistaの場合、KB971513はKB971644に含まれています。これらの更新プログラムは2009/10月末から11月初めに公開されています。 http://support.microsoft.com/kb/971513/ja VistaのVisual C# 2008 Experess Editionでコンソールプログラムを作成し、Windows XPでも動作することを確認しました。 PowerShellでスクリプト風に実行できるかどうかは研究中です。 ----- using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Windows.Automation; using System.Runtime.InteropServices; // 下記を参照に追加する。 // System.Drawing, System.Windows.Forms, UIAutomationClient, UIAutomationTypes, WindowsBase namespace TrayClick { class Program { // SendInputのための宣言は、緑のバイクさんの 初めてのC# ~覚え書き~ // マウスの自動操作をコピーする。38行省略。 // http://homepage3.nifty.com/midori_no_bike/CS/userIO.html#268 static void Main(string[] args) { AutomationElement aeDesktop = null; aeDesktop = AutomationElement.RootElement; if (aeDesktop == null) throw new Exception("内部エラー - デスクトップが求まらない。"); AutomationElement aeTray = null; aeTray = aeDesktop.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "通知領域")); if (aeTray == null) throw new Exception("内部エラー - 通知領域が求まらない。"); AutomationElement aeTarget = null; aeTarget = aeTray.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "秀丸エディタ")); if (aeTarget == null) { MessageBox.Show("指定のアイコンが見つかりません。", "エラー"); return; } if (aeTarget.Current.IsOffscreen) { MessageBox.Show("指定のアイコンは画面外です。", "エラー"); return; } System.Windows.Point clickablePoint = aeTarget.GetClickablePoint(); Rectangle rec = Screen.PrimaryScreen.Bounds; INPUT[] input = new INPUT[3]; input[0].mi.dx = screen_length * (int)clickablePoint.X / rec.Width; input[0].mi.dy = screen_length * (int)clickablePoint.Y / rec.Height; input[0].mi.dwFlags = MOUSEEVENTF_MOVED | MOUSEEVENTF_ABSOLUTE; input[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN; input[2].mi.dwFlags = MOUSEEVENTF_LEFTUP; SendInput(3, input, Marshal.SizeOf(input[0])); // アイコンをクリックする。 System.Threading.Thread.Sleep(100); // 必要があればメニューが出るのを待つ。 SendKeys.SendWait("O"); // 文字を送る。 } } } -----
その他の回答 (1)
- SHIMAPEE
- ベストアンサー率75% (154/203)
回答番号:No.1の補足へのアドバイス(というか私の勉強の経過)です。 WindowsオートメーションAPIにはInvokeメソッドがあってボタンを押すことも自動化できます。しかしあまり融通はきかず、マウスの右クリック相当はできません。そこで回答1ではSendInput APIを使ってみたのでした。 今日はMissing0001さんの言われるようにSendInputをメッセージに置き換えてもできるかなと思って試してみたのですが、結果としてはうまくいっていません。 WM_SETCURSOR, WM_MOUSEMOVE, WM_MOUSEACTIVATE, WM_LBUTTONDOWN, WM_LBUTTONUPの順序で送ってみたのですが、なぜだかWM_MOUSEMOVEの後にWM_MOUSELEAVEが挿入されてしまい、WM_LBUTTONDOWNに失敗しています。結局、マウスを移動するしかないのかもしれません。 メッセージへの置き換えに挫折し、現在、私の興味はWindowsオートメーションAPIとSendInputを使った汎用的なプログラムを作ることにあります(アイコンテキストとマウスのLRボタンを外から指定できるようにする)。回答1のプログラムを少し改造すればバージョン0.5は完成です。できた暁には、TrayClick.exeという名前で公開したいと思います。(googleで検索したところ、そのようなプログラム名は世界中になさそうです。需要がないということかもしれません。笑)
お礼
回答ありがとうございます。 調べているうちに、WShellでは無理かもって思い始めてたんです。 やっぱり無理だったんですね・・・。 自分のこんな質問に、時間が掛かりそうなソースを考えてくれてありがとうございます。 また、ゆっくりと内容を読ませていただきます。
補足
質問内容から離れますが・・・。 現在、ウィンドウハンドルと送られるメッセージがわかれば、 ウィンドウに直接メッセージを送って実行出来たりしないかなぁって考えたりしています。 これについてわからない事があればまた別件として質問しなおします。