きなこもち.net

.NET Framework × UiPath,Orchestrator × Azure × AWS × Angularなどの忘備録

UWP × GlobalHooks × 使えない理由を検証してみた

この記事の目的

この記事では、
UWPでGlobal Hookが機能するかについての検証結果をまとめること
を目的としています。

本題

★きっかけ

WPFでGlobalHookを使ったツールを作成しました。

作ったツールは、以下の機能を有しています。
1)GlobalHookを使って、ユーザー操作(マウスクリックやキーダウンなど)イベントを取得する。
2)イベントをきっかけにスクリーンショットを取得する。
3)エクセルファイルに2)で取得したスクショを時系列順に貼り付ける。

主に、何かのアプリのテストを手動で実行し、そのエビデンスを作成するときや、
何かの作業(特にGUIで操作するもの)を行うとき、その操作手順を記録するとき
に利用することを目的としたツール*1となっています。


このツールの配布の方法を考えたとき、GitHubからダウンロードするより、
UWPのほうが便利かと思い、WPF→UWPへつくりかえようと考えました。

UWPへのつくりかえにあたり、大きな問題となったのは、
スクリーンショットの取得
・エクセルファイルの出力
GlobalHookを使ったユーザー操作イベントの取得
です。

ということで、3つ目のGlobalHookが機能するかについて調べ始めました。

調べ始めてすぐに、StackOverFlowにて、GlobalHookがUWPで使えないという回答を見つけました。
stackoverflow.com


(自分が正しく議論が理解できていたら)
UWPではGlobalHookの選択肢はないということになります。

使えないってどういうことか・・・
コンパイルが通らないレベル?
実行時にエラーになるレベル?

という疑問があったので、どんなふうに”使えない”のか実際にサンプルを作って試してみることにしました。


★開発環境情報

Windows 10 1803
Visual Studio 2017 15.7.2
Grobal Hook Classはここのクラスを使いました。
github.com


★実装

UWPの画面自体はとてもシンプルで、
テキストブロックが1つだけある画面を作成しました。
テキストブロックの名前は"Sample"です。
f:id:kinakomotitti:20180526145633p:plain

画面が準備できたので、コードビハインドの実装をしていきます。

Hook時の操作を実装するメソッドを以下のように定義します。
以下の例では、マウスの左クリックイベントを拾うように定義します。

        void MouseHook_LeftButtonDown(GrobalHooks.MouseHook.MSLLHOOKSTRUCT mouseStruct) 
       {
            //TEXT BLOCKに実行時間を表示させる
            this.Sample.Text = DateTime.Now.ToString(”yyyyMMdd-HHmmss.ffffff”);
        }


次に、Hookのイベントを登録する処理を定義します。

        public void InitializeHooks()
        {
            // register events
            mouseHook.LeftButtonDown += new GrobalHooks.MouseHook.MouseHookCallback(MouseHook_LeftButtonDown);

            //開始
            mouseHook.Install();
            keyboardHook.Install();
        }


InitializeHooksメソッドを画面クラスの初期化時に呼び出します。

        public MainPage()
        {
            this.InitializeComponent();
            this.InitializeHooks();
        }
★動作確認!

実行したところのイメージは以下のようになります。
※初期表示時は”AAA”と表示しています。
 クリックすると、フックしたイベントが実行され、時刻を更新します。
 表示形式は、yyyyMMdd-HHmmss.ffffffです。

f:id:kinakomotitti:20180526145957g:plain



とりあえず・・・・


動いた(´▽`)
なんやかんやでUWPでもGlobalHookは動作することがわかりました!


★問題

しかし、そう簡単にはいかないようです(´・ω・`)


フックしたイベントは、UWPのアプリウィンドウの領域だけでしか発生しませんでした。。。
つまり、ウィンドウの領域外の部分での操作はフックできません。。。


これでは、ツールの目的を達成することができません。。。


上記の動作が本当だとしたら、考えられる対応としては、
UWPアプリを全画面表示させ、背景を透明にする
ことでしょうか( ゚Д゚)

そこまでいったら、グローバルフックではなく、画面のクリックイベントを拾えばよいですねw

まとめ

GlobalHookはUWPでも動作することが確認できた。
ただし、UWPのウインドウの中の操作に限る。←これが問題。。。
これがStackOverFlowでいわれていた”使えない”の理由なのだと感じました。

UWPだけでなく、フルスクリーンに対しての操作をフックしたい場合は
WPFWindows Formsを利用する必要がありそうです(=_=)

*1:つまらないものですが、プレリリース版は以下のURLで公開しています。 github.com