質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

2回答

8730閲覧

【C#】プロセスのIDが違う?そうです

abi-nitio

総合スコア37

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2016/02/01 14:05

こんにちは。

C#で作成しているアプリケーションで、外部アプリケーションを呼び出す際に、

Process ppp = Process.start(メモ帳)

のようにすると、メモ帳が立ち上がります。
その後、メモ帳にある文字列を出力し、保存をしたらメモ帳を閉じたいのですが、閉じることができません。

閉じる際は、ppp.Kill()のようにして、閉じよいと思っておりますが、プロセスidにひもづくプロセスは既に終了している、のようなニュアンスのメッセージがでてきます。
自分でも調べてみると、process.startの際に作成されるプロセスのIDはリアルなものではなく、偽物と言いますか、便宜上つけた値であることが原因で、killしようとしたプロセスはありません、のようなことになることがわかりました。

しかしながら、原因はそれなりにわかったつもりでも、どのような処理を施すと、リアルなプロセスをkillできるのかを知りたいです。

どうぞよろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hsk

2016/02/02 01:11

差支えない範囲で、ソースコードをご提示いただくことは出来ますか?
abi-nitio

2016/02/02 02:20

質問を閲覧頂きましてありがとうございます。 顧客先のPCで作業を行っているため、なかなかソースは書けませんが、やりたいことと引っ掛かってしまったことを以下に書きます。 今回行いたいことのシナリオは、仕事現場で開発が終わったので、テスト行程に移ったことで、エビデンスをたくさんとらなければならず、手でとるのも時間がかかるし馬鹿馬鹿しいし、というのでエビデンスの自動生成を行うかんたんなツールを作りました。 簡単に済ませたいので、Windowsフォームアプリケーションを使用して作成しました。 ボタンを押すと、 Process ppp = Process.Start(アプリ名) を通過し、画面のハードコピーを取得して保存するというものですが、アプリ自体は立ち上がります。しかしながら、ppp.idによりidプロパティから取得した値と一致する値がありません。(タスクマネージャのサービスタブのpidと比べました) そのためか、ppp.Kill()をすると、プロセスは既に終了しているという趣旨のエラーが出てしまいます。 質問では、メモ帳を開いてkillできないと書いておりましたが、上記のやりたいことを書くのは長いかなと思いまして、本質が同じであれば良いかなということで、メモ帳を例に質問をさせていただきました。 どうぞよろしくお願いします。
hsk

2016/02/02 02:33 編集

なるほど、わかりました。 otnさんが仰られているような、Kill前にプロセスが終了してしまっている可能性がありますね。 ちなみに起動対象が”メモ帳”でしたら、ツールは正常に動きますか? 無駄かもしれませんが、テストツール側も含めて1つずつ切り分けをして、確実かどうか確認されることをおすすめします。
abi-nitio

2016/02/02 02:43

メモ帳もエクスプローラもkillできませんでした。デバックをしながら、idを確認しているのですが、サービスのpidには合致するidは現れません… 回答して下さったcatsforepawさんのしているような、単純なプロセス起動とプロセス中断さえもidが存在しないために、エラーになります…
hsk

2016/02/02 02:55 編集

ツールが怪しい感じです...catsforepawさんのコードをそのまま試すと、私のほうでは、うまくいきます。 ちなみに余談ですが、エクスプローラ(explorere.exe)に限っては、特別な動きをするプログラム(シェル)なので、今回のような起動・終了テストでは使わないほうがいいです... 擬似ハンドル...の点で少し頭をよぎりましたが、WinExec API や、Cランタイムの beginthread を利用しているのではないですよね?System.Diagnostics.Process クラスのStartメソッドあたりを使われているのですよね?
abi-nitio

2016/02/02 03:08

お昼ご飯を済ませてからもう一度トライしてみますが、今回のツールを使ってとりたいエビデンスのメインはエクスプローラの画面なのですが、特別な動きをする、ということはやめておいた方が無難なのでしょうか…
abi-nitio

2016/02/02 04:01

申し訳ございませんでした。メモ帳はkillすることができました。プロセスのidプロパティとサービスのpidが一致しなくても問題ないのですね。一致するidがないためにkillできないと決めつけてしまっておりました。しかしながら、エクスプローラのkillはやはりできませんでした。難しそうではありますが、手続きを踏めばできないことはないでしょうか。
hsk

2016/02/02 05:25 編集

ためしに、エクスプローラーの画面を手操作でもよいので複数開いてみると、タスクマネージャーでexplorer.exeのエントリ数は1つだけであることが確認できます(複数起動させる、例外設定もできますが)。エクスプローラーは、基本的に多重起動しないようになっていて、explorer.exe は自分が開かれたときにすでエクスプローラーが動いていたら、先輩に自分がしようとしていた処理をゆだねて、自分自身は終了させてしまいます。ちなみに「サービスのpid」とありますが「サービスプロセス」を動かそうとしているのではないですよね?
hsk

2016/02/02 05:33

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
abi-nitio

2016/02/02 12:49

お返事が遅れまして申し訳ございません。別プロセスでエクスプローラが開くように設定はしたのですが、やはりエラーが起きてしまい、内容も変わりませんでした。しかしながら、エクスプローラの扱いは少し特殊になる、ということを知れたので非常に勉強になりました。 当分は、起動したエクスプローラは手で消していこうと思います。
hsk

2016/02/03 00:00 編集

もし、ウインドウタイトルがユニークなのであれば、FindWindowでタイトルに一致したウインドウハンドルを探して、プロセスを止めるのではなく、そのウインドウにWM_CLOSEメッセージを飛ばせば、閉じます(FindWindowでウインドウを探し、SendMessageでWM_CLOSEメッセージを送ります) http://blogs.yahoo.co.jp/koga2020/54275972.html http://dobon.net/vb/dotnet/process/getprocessesbywindowtitle.html
guest

回答2

0

それ、ほんとにメモ帳(=Windows標準のnotepad.exe)ですか?別のアプリでは?
アプリによっては、子プロセスを生成して親はすぐ終わっちゃう物もありますよ。

投稿2016/02/01 15:21

otn

総合スコア84533

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

catsforepaw

2016/02/01 15:28

その可能性もありますね。"notepad"と書かずにメモ帳としているところが引っかかってはいたのですが、そこまで思いが至りませんでした。
guest

0

ちょっと状況がよく判りません。
Startメソッドで開始したプロセスは、Killメソッドで中止できます。

自分でも調べてみると、process.startの際に作成されるプロセスのIDはリアルなものではなく、偽物と言いますか、便宜上つけた値であることが原因で、killしようとしたプロセスはありません、のようなことになることがわかりました。

それは間違いです。ProcessのIdプロパティは「リアルなもの」であり、システムで付けられたプロセスIDそのものです。ですので、StartさせたProcessオブジェクトのIdプロパティをどこかに表示させて、タスクマネージャーの詳細で表示されるPIDと比べれば同じであることが判ります。

Process ppp = Process.start(メモ帳)

試しに以下のコードを実行してみてください。メモ帳を開いて3秒後に閉じるはずです。

C#

1Process proc = Process.Start("notepad"); 2System.Threading.Thread.Sleep(3000); 3proc.Kill();

Process ppp = Process.start(メモ帳)

Killしようとしたプロセスがこのpppであることは間違いないのでしょうか? Killする前に何か別のものに置き換わってしまったら当然Killできません。

投稿2016/02/01 15:00

catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問