タスクマネージャへのタブページ追加

[戻る]
だくだく 2006/07/16(日) 23:51:45
標準タスクマネージャにタブページを追加し、それに配置したコントロールを操作した
いと考えております。
作成したDLLをアプリ側からCreateRemoteThreadとLoadLibraryを用いてインジェクショ
ンし、アタッチされたら
ページをダイアログボックスで作成して追加し、タスクマネージャのプロシージャをサ
ブクラス化
してタブページの制御というようにしたいと思っています。

しかし、以下のソースを実行すると、ページは追加されるのですが作成したタブに切り
替えようとすると
ハンドルされていないWin32の例外が発生しましたとエラーが出てしてしまいます。
いろいろ見てみるとg_hAddTab値がNULLで、タブページの元となるダイアログが作成され
ていないようです。
ダイアログはこちらを参考に作成いたしました
http://home.a03.itscom.net/tsuzu/programing/tips28.htm
ダイアログリソースはDLL内にあります
なお、タスクマネージャのインスタンスハンドルやウィンドウハンドルはきちんと取れ
ております
なぜダイアログが作られないのか、わかりません
よろしければアドバイスいただけないでしょうか?

VS.NET2003 VC++ 非MFCです

-----DLL-----

<DllMain>
case DLL_PROCESS_ATTACH:
    g_hDll = hInstance;
    Initialize();

<Initialize>
//タスクマネージャのインスタンスハンドルを取得
    g_hTaskManagerInst = (HINSTANCE)GetWindowLong(g_hTaskManager, 
GWL_HINSTANCE);
//タスクマネージャプロシージャのサブクラス化
    g_OriginalTaskManagerWndProc = (WNDPROC)SetWindowLong(g_hTaskManager, 
GWL_WNDPROC, (LONG)NewTaskManagerWndProc);
//タブコントロールへのページの追加
    TabCount = TabCtrl_GetItemCount(g_hTaskTab);
    TabCtrl_InsertItem(g_hWndTaskTab, TabCount+1, &tc);
//ページの作成
    g_hAddTab = CreateDialog(g_hTaskManagerInst, (LPCTSTR)IDD_ADDTAB_1, 
g_hTaskManager, (DLGPROC)AddTabProc);
    ShowWindow(g_hAddTab, SW_HIDE);
//ページの配置


<サブクラスプロシージャ>
LRESULT CALLBACK NewTaskManagerWndProc(HWND hWnd, UINT msg, WPARAM wParam, 
LPARAM lParam)
{
    NMHDR *nm = (NMHDR*) lParam;
    
    switch(msg)
    {
    case WM_NOTIFY:
        switch(nm->code)
        {
        case TCN_SELCHANGE:
            if(nm->hwndFrom == g_hWndTaskTab)
            {
                switch (TabCtrl_GetCurSel(g_hWndTaskTab))
                {
                case 1:
                case 2:
                case 3:
                case 4:
                    ShowWindow(g_hAddTab, SW_HIDE);
                    break;
                case 5://追加したタブページが選択されたとき
                    MessageBox(hWnd, "aaa", "", 
MB_OK);
                    ShowWindow(g_hAddTab, SW_SHOW);
                    ShowWindow(g_hOriginalTabPage[0], 
SW_HIDE);
                    ShowWindow(g_hOriginalTabPage[1], 
SW_HIDE);
                    ShowWindow(g_hOriginalTabPage[2], 
SW_HIDE);
                    ShowWindow(g_hOriginalTabPage[3], 
SW_HIDE);
                    ShowWindow(g_hOriginalTabPage[4], 
SW_HIDE);
                    break;
                }
            }
            break;
        }                
        break;
    }
    return CallWindowProc(g_OriginalTaskManagerWndProc , hWnd , msg , 
wParam , lParam);
}

だくだく 2006/07/18(火) 09:16:50
CreateDialogの第1引数はタスクマネージャではなくDLLリソースのある
DLLのハンドルを指定しなければいけなかったのですね。。。
ただ、ここを修正しても、追加されたタブを選択すると相変わらず強制終了
してしまいます。
なぜかお分かりになる方いらっしゃいましたらよろしくお願いします

ITO 2006/07/18(火) 09:42:30
DLLでやることに無理はないですか?
普通に標準タスクマネージャにタブページを追加できるのですか?
WindowsNTサービスアプリケーションのようなもので作らないといけないの
ではないですか。

r 2006/07/18(火) 09:43:46
タスクマネージャの本来のウィンドウプロシージャ
(g_OriginalTaskManagerWndProc)
は、追加タブページがあることを知りません。
処理しないメッセージだけを本来のウィンドウプロシージャに
渡すようにしないと...

r 2006/07/18(火) 09:48:52
ITOさん曰く、
>DLLでやることに無理はないですか?
無理がないとは言い切れないですね。
タスクマネージャをどうにかしようなんて危ういことは避けたほうが無難。
(何とかなりそうな気はするけど...)

ITO 2006/07/18(火) 10:28:59
>>DLLでやることに無理はないですか?
>無理がないとは言い切れないですね。
普通のダイアログ作成なら無理はないと思いますが、
相手が「タスクマネージャ」なので「HWND」が確立していないと
難しいのではないかと思いました。
しかも、タブページの追加となるとなおさら.....

だくだく 2006/07/18(火) 11:02:01
レスありがとうございます

>タスクマネージャの本来のウィンドウプロシージャ
>(g_OriginalTaskManagerWndProc)
>は、追加タブページがあることを知りません。
>処理しないメッセージだけを本来のウィンドウプロシージャに
>渡すようにしないと...


これは重々承知しておりまして、
サブクラス化したNewTaskManagerWndProcのcase 5(追加ページが選択されたとき) で
追加したタブページの表示をしてあとはg_OriginalTaskManagerWndProcに渡したのです
がいけないのでしょうか?
追加ページ内のコントロール類の処理は追加したダイアログプロシージャでやります
し・・・

>タスクマネージャをどうにかしようなんて危ういことは避けたほうが無難。
これも承知してはいるのですが、せざるを得ない状況でして。。。

>相手が「タスクマネージャ」なので「HWND」が確立していないと
>難しいのではないかと思いました。
タスクマネージャのウィンドウハンドルは正しいものが取れていることをSpy++で
確認しているのですが、それでも難しいものなのでしょうか?

r 2006/07/18(火) 11:20:02
>これは重々承知しておりまして、
>サブクラス化したNewTaskManagerWndProcのcase 5(追加ページが選択されたとき) で
>追加したタブページの表示をしてあとはg_OriginalTaskManagerWndProcに渡したのです
>がいけないのでしょうか?

承知してるなら、何故渡すのですか?
追加タブページを知らない人に追加タブページが選択されたことを
知らせたら、何が起きても不思議ではないでしょう?

だくだく 2006/07/18(火) 11:39:40
勘違いしていたら申し訳ありません。
追加タブページが選択されたことは自作したプロシージャNewTaskManagerWndProcに知ら
せてそこで処理を行い、それ以外は元のプロシージャg_OriginalTaskManagerWndProcに
渡しているつもりだったのですが、間違っているのでしょうか?
これでも追加タブページを知らないプロシージャに知らせていることになるのでしょう
か?

ITO 2006/07/18(火) 11:40:23
>タスクマネージャのウィンドウハンドルは正しいものが取れていることをSpy++で
>確認しているのですが、それでも難しいものなのでしょうか?
確認できているから、それをDLLで使えるとは思えないのですが.....
DLLでなくメインウインドウのHWNDが確立しているところでそのサブウインドウとして
操作することは難しいとけれども可能だと思います。

ITO 2006/07/18(火) 11:45:23
追加です、
DLLは、あくまでもライブラリーという扱いで、
ウインドウ作成等は、アプリケーションで行うのなら話は、別ですが.........

r 2006/07/18(火) 11:53:16
>case 5://追加したタブページが選択されたとき
のときも break で抜けて CallWindowProc をコールしてるから、
g_OriginalTaskManagerWndProc に渡してることになります。
まぁ、ここだけ直せばすべてうまくいくなんて保証なんてどこにも
ありませんけどね...

r 2006/07/18(火) 12:12:33
あぁ、あとCreateDialog()の第一引数はg_hDllでないと
いけないんじゃなくて?

ITO 2006/07/18(火) 12:13:06
>これでも追加タブページを知らないプロシージャに知らせていることになるのでしょう
>か?
「元のプロシージャ」は、そのメッセージを受取れる状態になっていますか?
メッセージを送っても相手が待ち受けてる状態にならなければ、うまくいきません。

「タスクマネージャ」は、ウインドウズのシステム管理で動いている
アプリケーションです。
待ち受けてる状態にはなっているとは思えないのですが......

r 2006/07/18(火) 13:43:04
>あぁ、あとCreateDialog()の第一引数はg_hDllでないと
>いけないんじゃなくて?

あ、これはもう [だくだく 2006/07/18(火) 09:16:50] で修正済みなのね。

Ban 2006/07/18(火) 14:10:51
基本的には r さんの発言に同意。
> 無理がないとは言い切れないですね。
> タスクマネージャをどうにかしようなんて危ういことは避けたほうが無難。
> (何とかなりそうな気はするけど...)

まずは、適当な別のタブ付きダイアログで試すのが、切り分けの意味でも安全だとは思いますが。


>ITO さん
# DLL の用途を限定するのは、定石的な正攻法という意味で正しい面もあると思いますが、
# DLL のポテンシャル自体はもっと高く広いものですし、インジェクションしてるような
# コードでそれを論じてもあまり意味がない気がします。

dairygoods 2006/07/18(火) 14:11:33
CreateDialog が失敗するのでしたら、
GetLastError() で何かわかりませんか?

r 2006/07/18(火) 15:13:23
TCN_SELCHANGEよりも前に発生するであろう、
TCN_SELCHANGINGでも騙しておかないと駄目かもしれない。

その他にもいろいろ障壁はあるかもしれない。
追加ダイアログから親ウィンドウへ送られるメッセージ類
(WM_INITDIALOGなど)は放っておいても大丈夫なんだろうかとか、
他のダイアログをShowWindowなどで操作することで内部矛盾が生じて
癇癪起こしたりしないんだろうかとか。
騙したい相手が画面をどのように管理してるのかわからないのだから、
どうすれば間違いなく動くのかという確証も決して得られはしないと思われ。

#DLLインジェクションはシェル拡張みたいに公式な手法ではなく
#騙しの手法だから、「良い子は真似をしないでね」の世界。
#なので、アドバイス可能なのもせいぜいこの程度。
#その先は何があろうと自力で何とかするご覚悟を。

だくだく 2006/07/18(火) 19:32:26
みなさんアドバイスありがとうございます
やはりかなり難しいですね。。。
また進展がありましたら書き込みますのでよろしくお願いします

ITO 2006/07/18(火) 20:21:26
># DLL の用途を限定するのは、定石的な正攻法という意味で正しい面もあると思います
が、
># DLL のポテンシャル自体はもっと高く広いものですし、インジェクションしてるよう># コードでそれを論じてもあまり意味がない気がします。
そうですね、DLLというとライブラリーという観点に立ってしまってまずいですね。
そういえば、共有プロセスの件の時もDLL使ってましたね。

r 2006/07/18(火) 20:27:05
DLL_PROCESS_ATTACH 内で CreateDialog() を実行しているので、
ダイアログ作成は LoadLibrary() を呼び出したスレッド
(たぶんリモートスレッド)のコンテキストで実行されている。
リモートスレッドがメッセージループを回さずに終了しているなら、
タブをクリックする前にダイアログは破棄されているだろう。
どのウィンドウがどのスレッドに属していて、どんな具合に動いて
いるのかが理解できていないと、進展は程遠い。
あと、DLL の生存期間を超えてサブクラス化したままだったら、
そこでお亡くなりになるだろう、ってことも容易に想像できる範囲。
このあたり、ちゃんと考えて制御してますか?

#誰のゴリ押しでやるはめになってるのか知らないけど、
#進展などできずにギブアップするほうが、幸せかも。

ITO 2006/07/18(火) 21:15:02
これらは、うまくいってますか?
>//タスクマネージャのインスタンスハンドルを取得
>    g_hTaskManagerInst = (HINSTANCE)GetWindowLong(g_hTaskManager, 
> GWL_HINSTANCE);
> //タスクマネージャプロシージャのサブクラス化
    g_OriginalTaskManagerWndProc = (WNDPROC)SetWindowLong(g_hTaskManager, 
> GWL_WNDPROC, (LONG)NewTaskManagerWndProc);

古いスレッドには追加発言できません。