- PR -

C# グローバルフックでメッセージを編集して送り返す。

投稿者投稿内容
Makoto
大ベテラン
会議室デビュー日: 2004/03/31
投稿数: 133
投稿日時: 2007-01-26 14:35
>Microsoft.NET Frameworkではね。

>なるほどー、明言しちゃってるから例外があることは分からないですね。

上記発言を踏まえたうえで確認したいんですが、
C#でグローバル フックすることは可能ということですか?

確かに最近サンプルソースを見かけることがありますので、
気になってはいたのですが...
『C++でAPIプログラムするのに比べて制約がある!?』
というレベルなのでしょうか?

あるいは、『グローバル フックは .NET Framework ではサポートされていない』
は、つまりC#でもpInvokeで可能というニュアンスですか!?

【MSサイトより抜粋】
>DLL エクスポートは、.NET Framework でサポートされていません。
>関数ポインタは動的にビルドされるプロキシであるため、
>マネージ コードには関数ポインタの一貫した値の概念がありません。

この説明読むと、『CLRで処理されるプログラムでは不可能なのでは!?』
とも思いますし...
どういうことなんでしょうか?
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-01-26 19:33
引用:

C#でグローバル フックすることは可能ということですか?



このスレッドの最小の方で「低レベルフックなら可能」と書きました。

引用:

『C++でAPIプログラムするのに比べて制約がある!?』
というレベルなのでしょうか?



このスレッドをまとめて読めば分かると思いますが

・低レベルフックのみ可能
・低レベルフックではメッセージの置換は出来ない
・低レベルフックでもメッセージの伝播を絶つことは可能

ということになります。

メッセージ置換が目的の場合も多いと思いますが、そういう用途には「使えない」ことになります。

引用:

>関数ポインタは動的にビルドされるプロキシであるため、
>マネージ コードには関数ポインタの一貫した値の概念がありません。

この説明読むと、『CLRで処理されるプログラムでは不可能なのでは!?』
とも思いますし...



私見ですが、これもかなり大雑把で表面的な説明だと思います。
これ「だけ」が問題ではないし、これが最も大きな問題だとは思いません。

少なくとも、C++/CLI を使えばこの部分の制限は回避することが出来ます。

個人的には、「同一プロセス内に異なるバージョンの .NET Framework ランタイムは同居できない」ことの方が、グローバルフックを行う上での大きな障害だと考えています。

有末 清華
ベテラン
会議室デビュー日: 2006/10/09
投稿数: 52
お住まい・勤務地: 北海道
投稿日時: 2007-01-26 22:35
それのことです、できないって言われてしまっては…と。

でもできるのがLow Levelのマウスフック・キーボードフックなんで結局できないみたいな紋ですがね(汗。

Low LevelだとやりたいことができないようなのでC++/CLIでフックの部分だけ書くことにしました。 お騒がせしました m(_ _)m
_________________
有末 清華
crazy(){for;;{you();}} - プログラマの覚書
有末 清華
ベテラン
会議室デビュー日: 2006/10/09
投稿数: 52
お住まい・勤務地: 北海道
投稿日時: 2007-01-26 22:39
ん? C++じゃなきゃだめかな???

まぁまずは自分でいろいろ調べてから。

C#でフックをしたい方のためのリンク。

http://www.codeproject.com/csharp/globalhook.asp - LLを使ってc#でフック処理
http://www.codeproject.com/csharp/GlobalSystemHook.asp - Unmanaged C++ でやるっぽい…詳細はまだちゃんと見てないから不明。
_________________
有末 清華
crazy(){for;;{you();}} - プログラマの覚書
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-01-26 22:49
引用:

C++/CLIでフックの部分だけ書くことにしました。



キケンですよ。

フック DLL を .NET ランタイムとリンクしては駄目です。

理由は簡単、すぐ上で書いたように「同一プロセス内に異なるバージョンの .NET Framework ランタイムは同居できない」からです。
有末 清華
ベテラン
会議室デビュー日: 2006/10/09
投稿数: 52
お住まい・勤務地: 北海道
投稿日時: 2007-01-26 23:30
うぅーん。 ではC#では低レベルマウス処理以外のフックは基本的にできない(推薦されない)ということですよね。

さてこまったな(汗。
_________________
有末 清華
crazy(){for;;{you();}} - プログラマの覚書
有末 清華
ベテラン
会議室デビュー日: 2006/10/09
投稿数: 52
お住まい・勤務地: 北海道
投稿日時: 2007-01-26 23:34
引用:

When you think about how system hooks actually implement their functionality, it makes sense that we need unmanaged code. In order for a global system hook to work, Windows inserts your DLL into the process space of every running process. Since most processes are not .NET processes, they cannot execute .NET assemblies directly. We need an unmanaged code stub which Windows can insert into all the processes that will be hooked.



だそうです。だから先のリンク先ではDll二個作ってますね、話さらっと読んだ感じ。
Unmanaged C++とManaged C++の二つを作ってC#でManaged C++側を読み込んでいるんじゃないかな(あとでソース落として確認します)
_________________
有末 清華
crazy(){for;;{you();}} - プログラマの覚書
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2007-01-27 08:18
引用:

ではC#では低レベルマウス処理以外のフックは基本的にできない(推薦されない)ということですよね。



そうなります。

現状、100% pure C#(てか IL?)なコードでは、低レベルフック以外のフックは出来ません。

引用:

だそうです。



そんなもんでしょうね。

他プロセスのメッセージをフックした時、フックプロシージャは他プロセスのコンテキストで動作するので、その状態で .NET ランタイムを呼び出すことは非常に危険な行為なのでしてはいけません(=単純に失敗する場合もあれば、最悪の場合、ターゲットプロセスをクラッシュさせてしまします)し、プロセスが異なるわけですから、フック元のプロセスがロードしているアセンブリ内のメソッドを .NET ランタイムの力を使わずに呼び出すことも容易ではありません。

目的とする動作を得るためには、最低限、フック DLL は 100% pure レガシ DLL?として構成する必要があります。

で、フックしたメッセージをマネージコードで処理したいとすると、フック DLL が捕捉したメッセージの情報を、非 .NET 的な、なんらかのプロセス間通信手段によってマネージコードに転送しなければなりません。(しかも、メッセージ置換が目的なら同期的に)

ここの信頼性や保守性をキープするのはかなり面倒なので、腕の見せ所です (^^;;;



[ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2007-01-27 08:22 ]

スキルアップ/キャリアアップ(JOB@IT)