質問者
タスクマネージャーに表示されないプロセスについて

質問
-
すべての返信
-
質問時の情報が少なくあやふやでしたので、追加で調査した情報を追記します。
①起動方法
a.exeは直接起動(ダブルクリック等)ではなく、別途C言語で作成したプログラムからのCreateProcess関数による起動です。
この際、CreateProcess関数の引数は以下の通りでした。CreateProcess( NULL,
"a.exe",
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS | DETACHED_PROCESS,
NULL,
NULL,
&si,
&pi);
②WinServer2008 と WinServer2012 での挙動の違い上記の方法でWinServer2008で起動した場合、タスクマネージャーにはa.exeが表示されますが、
WinServer2012で起動した場合は、タスクマネージャーにはa.exeが表示されません。
ただし、リソースモニターやコマンドプロンプトでのtasklistコマンドでは表示されます。またa.exeではなく別のb.exeを同様に起動した場合に、WinServer2008でもWinServer2012でも
タスクマネージャーに表示されることも確認しました。
a.exeもb.exeも、ともにWin32コンソールアプリとしてC言語で作成しています。b.exeは別サーバと通信を行うプログラム、a.exeはローカル上のプログラムを監視して動作して
いなければ起動しなおすプログラムで、どちらも常駐して実行し続けるタイプのものです。
③調査情報
CreateProcessの第6引数dwCreationFlagsに指定している DETACHED_PROCESS を CREATE_NO_WINDOW に
変更することで、a.exeをWinServer2012のタスクマネージャーに表示できました。
以上が現時点で調査して分かっている情報です。ここからは質問なのですが、
質問1
WinServer2012のタスクマネージャーには起動していても表示されないプロセスがあるのでしょうか?
質問2
CreateProcessの第6引数に指定したDETACHED_PROCESSとCREATE_NO_WINDOWの違いなのですが、
下記の通りと認識しています。
・CREATE_NO_WINDOW
プロセスをコンソールウィンドウなしで実行する
・DETACHED_PROCESS
プロセスを親プロセスへのアクセス不可の状態で実行するただ、この違いがタスクマネージャーへの表示に影響するようには思えません。
何か他に違いがあるのでしょうか?以上、長くなってしまいました。
何かご存知の方がいらっしゃいましたら、よろしくお願い致します。 -
a.exe がゾンビ プロセス状態になっているのかも。
私のあてにならない記憶では、Task Manager はゾンビ プロセスを表示しないはず。。。だったと思います。
(OS に依存して、Task Manager の挙動が異なるのかも。)
例えば、a.exe プロセスが Terminate していていも、a.exe の Process Handle や Thread Handle を「外部の」プロセスが保持し続けている (クローズしない) 場合、a.exe プロセスは終了状態でメモリ上に残り続けます。とりあえず、明示的にゾンビ プロセスを作ってみて、その際の挙動を確認してみては?- 回答の候補に設定 佐伯玲 2016年6月1日 1:58
-
>お馬鹿 様
返信ありがとうございます。
ゾンビプロセスの可能性も考えたのですが…
a.exeからは正常にログが出力されており、プログラムの動作自体も
タスクマネージャーに表示されない以外は正常に見えるため、
その可能性はなさそうです。また昨日の調査で分かった追加情報なのですが、
タスクマネージャーに表示されるb.exeのDB接続処理部分を
コメントアウトすると、タスクマネージャーに表示されなくなりました。
ここまでの情報をまとめると、以下のような感じです。1.PG起動用exeからCreateProcess関数で起動したプロセスが
タスクマネージャーに表示されない。
リソースモニターやtasklistコマンドでは表示される。
CreateProcess関数の第6引数はDETACHED_PROCESS。2.タスクマネージャーに表示されないのはWinServer2012の場合のみで
WinServer2008ではタスクマネージャーに表示される。3.CreateProcess関数の第6引数をCREATE_NO_WINDOWに変更すると、
タスクマネージャーに表示されるようになる。4.CreateProcess関数を変更する前でもタスクマネージャーに表示される
プログラムもあるが、DB接続を行う処理をコメントアウトすると
タスクマネージャーに表示されなくなる。5.CreateProcess関数からではなくダブルクリック等で直接起動した場合は
タスクマネージャーに表示される。
CreateProcess関数で起動するプロセスにDB接続処理を含むかどうかで
タスクマネージャーに表示されるかどうかが変わるようですね… -
私の環境(Windows Server 2012R2)で試したところ再現しました。
CreateProcess(第6引数はDETACHED_PROCESS)で次のようなコードのプログラムを実行したところタスクマネージャーに表示されず。TaskListでは表示されました。
#include <stdio.h> #include <windows.h> int main() { while (true) { Sleep(1000); } return 0; }
メッセージを処理してないからかな?と思い試しに下記のように修正するとタスクマネージャーに表示されました。
#include <stdio.h> #include <windows.h> int main() { MSG msg = { 0 }; while (true) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) break; DispatchMessage(&msg); } } return 0; }
あくまで仮定ですがメッセージを処理するようにすればタスクマネージャーに表示されるのかもしれません。
追伸:2番目のプログラムでGetMessageを使ってましたがループのプログラムではPeekMessageのほうが適切かなと思いプログラムを修正しました。
なんとなく User32.dll がプロセスのアドレス空間にマッピングされるかどうかで、挙動が変わってくるんじゃないかなぁ
- 編集済み kenjinoteMVP 2016年7月3日 8:25
-
断言はできませんが、もしかしたら a.exe プロセスの EPROCESS オブジェクトを書き換えているカーネル モード側のソフトウェアが存在するのかも。
Windows で稼働中の個々のプロセスは EPROCESS オブジェクトとして表され、この EPROCESS 構造体メンバには LIST_ENTRY 構造体でプロセス チェーン情報が保持されています。
Task Manager も "System Idle Process" の EPROCESS から順番に LIST_ENTRY 内のプロセス チェーンをたどり、稼働中プロセスの列挙を行っています。
(この部分の詳細に関しては、こちらのサイトで詳しく解説されていますので、興味があったら参照してください。)つまり、個々の EPROCESS 内の LIST_ENTRY データとして保持されているプロセス チェーン情報を書き換えると、稼働中のプロセスであっても Task Manager から非表示にすることが可能なのです。
(マルウェアの中には、これをやるものもある。)
今回の現象がこれに該当するかは不明ですが、調べてみる価値はあるかも。すべてのプロセスの EPROCESS オブジェクトを確認するためには、カーネル モード接続でのライブ デバッグか、現象が発生している状態での「完全メモリ ダンプ」を採取しそれを調べるかの、いずれかになると思います。
Hyper-V などの仮想環境があるのであれば、WinDBG を簡単にカーネル デバッグ接続させることができるので、ライブ デバッグがお勧めです。- 回答の候補に設定 miyamamMicrosoft employee 2016年6月6日 9:32