こんにちは。
C#で作成しているアプリケーションで、外部アプリケーションを呼び出す際に、
Process ppp = Process.start(メモ帳)
のようにすると、メモ帳が立ち上がります。
その後、メモ帳にある文字列を出力し、保存をしたらメモ帳を閉じたいのですが、閉じることができません。
閉じる際は、ppp.Kill()のようにして、閉じよいと思っておりますが、プロセスidにひもづくプロセスは既に終了している、のようなニュアンスのメッセージがでてきます。
自分でも調べてみると、process.startの際に作成されるプロセスのIDはリアルなものではなく、偽物と言いますか、便宜上つけた値であることが原因で、killしようとしたプロセスはありません、のようなことになることがわかりました。
しかしながら、原因はそれなりにわかったつもりでも、どのような処理を施すと、リアルなプロセスをkillできるのかを知りたいです。
どうぞよろしくお願いします。
差支えない範囲で、ソースコードをご提示いただくことは出来ますか?
質問を閲覧頂きましてありがとうございます。
顧客先のPCで作業を行っているため、なかなかソースは書けませんが、やりたいことと引っ掛かってしまったことを以下に書きます。
今回行いたいことのシナリオは、仕事現場で開発が終わったので、テスト行程に移ったことで、エビデンスをたくさんとらなければならず、手でとるのも時間がかかるし馬鹿馬鹿しいし、というのでエビデンスの自動生成を行うかんたんなツールを作りました。
簡単に済ませたいので、Windowsフォームアプリケーションを使用して作成しました。
ボタンを押すと、
Process ppp = Process.Start(アプリ名)
を通過し、画面のハードコピーを取得して保存するというものですが、アプリ自体は立ち上がります。しかしながら、ppp.idによりidプロパティから取得した値と一致する値がありません。(タスクマネージャのサービスタブのpidと比べました)
そのためか、ppp.Kill()をすると、プロセスは既に終了しているという趣旨のエラーが出てしまいます。
質問では、メモ帳を開いてkillできないと書いておりましたが、上記のやりたいことを書くのは長いかなと思いまして、本質が同じであれば良いかなということで、メモ帳を例に質問をさせていただきました。
どうぞよろしくお願いします。
なるほど、わかりました。
otnさんが仰られているような、Kill前にプロセスが終了してしまっている可能性がありますね。
ちなみに起動対象が”メモ帳”でしたら、ツールは正常に動きますか?
無駄かもしれませんが、テストツール側も含めて1つずつ切り分けをして、確実かどうか確認されることをおすすめします。
メモ帳もエクスプローラもkillできませんでした。デバックをしながら、idを確認しているのですが、サービスのpidには合致するidは現れません…
回答して下さったcatsforepawさんのしているような、単純なプロセス起動とプロセス中断さえもidが存在しないために、エラーになります…
ツールが怪しい感じです...catsforepawさんのコードをそのまま試すと、私のほうでは、うまくいきます。
ちなみに余談ですが、エクスプローラ(explorere.exe)に限っては、特別な動きをするプログラム(シェル)なので、今回のような起動・終了テストでは使わないほうがいいです...
擬似ハンドル...の点で少し頭をよぎりましたが、WinExec API や、Cランタイムの beginthread を利用しているのではないですよね?System.Diagnostics.Process クラスのStartメソッドあたりを使われているのですよね?
お昼ご飯を済ませてからもう一度トライしてみますが、今回のツールを使ってとりたいエビデンスのメインはエクスプローラの画面なのですが、特別な動きをする、ということはやめておいた方が無難なのでしょうか…
申し訳ございませんでした。メモ帳はkillすることができました。プロセスのidプロパティとサービスのpidが一致しなくても問題ないのですね。一致するidがないためにkillできないと決めつけてしまっておりました。しかしながら、エクスプローラのkillはやはりできませんでした。難しそうではありますが、手続きを踏めばできないことはないでしょうか。
ためしに、エクスプローラーの画面を手操作でもよいので複数開いてみると、タスクマネージャーでexplorer.exeのエントリ数は1つだけであることが確認できます(複数起動させる、例外設定もできますが)。エクスプローラーは、基本的に多重起動しないようになっていて、explorer.exe は自分が開かれたときにすでエクスプローラーが動いていたら、先輩に自分がしようとしていた処理をゆだねて、自分自身は終了させてしまいます。ちなみに「サービスのpid」とありますが「サービスプロセス」を動かそうとしているのではないですよね?
explorer.exeを複数起動させるようにする設定は「フォルダオプション」設置で「別のプロセスでフォルダーウィンドウを開く」をONにすればできます。が、お望みの動作をするかどうかは保証できません(OSのバージョンによって挙動が違うかもしれません)
http://answers.microsoft.com/ja-jp/windows/forum/windows8_1-files/windows81%E3%81%AEexplorer%E3%81%AE%E3%83%95/0319b4c2-3dbe-4820-8309-fced05fefe4d
お返事が遅れまして申し訳ございません。別プロセスでエクスプローラが開くように設定はしたのですが、やはりエラーが起きてしまい、内容も変わりませんでした。しかしながら、エクスプローラの扱いは少し特殊になる、ということを知れたので非常に勉強になりました。
当分は、起動したエクスプローラは手で消していこうと思います。
もし、ウインドウタイトルがユニークなのであれば、FindWindowでタイトルに一致したウインドウハンドルを探して、プロセスを止めるのではなく、そのウインドウにWM_CLOSEメッセージを飛ばせば、閉じます(FindWindowでウインドウを探し、SendMessageでWM_CLOSEメッセージを送ります)
http://blogs.yahoo.co.jp/koga2020/54275972.html
http://dobon.net/vb/dotnet/process/getprocessesbywindowtitle.html