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

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

新規登録して質問してみよう
ただいま回答率
85.34%
ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

Q&A

1回答

463閲覧

C# 実行中のプロセスを取得し、プロセスのファイルパスを参照して、指定したフォルダより下層のexeを全て終了させたい。

mysknj

総合スコア4

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

0グッド

1クリップ

投稿2024/11/24 05:50

編集2024/11/25 17:04

実現したいこと

Windowsフォームにて実行中のプロセスを取得し、取得したプロセスのファイルパスを参照して、指定したフォルダより下層にあるexeを全て終了させるプログラムを作りたいのですが、以下を試しても、目的の挙動が得られませんでした。現状の処理では取得したファイルパスに該当の文字列が含まれる場合はプロセスを終了という風に記載してますが、そもそもそれすら通りません。
こちらどなたか解決策をご教示いただけないでしょうか。

背景としましては
①フォームからexeを指定して実行
②実行したプロセスの終了
まではできたのですが、実行したexeの中には指定したexeを実行後に、さらに下層のフォルダのexeを開くという挙動をしているexe指定したexeを実行後に、さらに下層のフォルダのexeを開き、最初に開いたexeは既に終了しているという挙動をしているexeがありまして、その場合さらに下層のexeまでは終了できなかったため、全て終了させる手段として、実行中のプロセスのファイルパスを取得し、そのパスの中に該当の文字列が含まれている場合にプロセスを終了という形をとっています。
※おそらく現状だと最終的に残っているプロセスは最初に開いたプロセスの子や孫には該当しませんよね?

※もちろん、それでも条件によっては目的のexeが終了できない場合があることは分かってます。なので、そこも解消すべく、指定したフォルダより下層にあるexeを全て終了させるなどの事ができればなお良いです。ご教示お願いいたします。

発生している問題・分からないこと

実行中のプロセスの中に、指定した文字列がファイルパスに含まれる場合、プロセスを終了させたい。

該当のソースコード①で発生している事象は

例外がスローされました: 'System.ComponentModel.Win32Exception' (System.dll の中)

となり、そもそもプロセス終了の処理を通りません。

該当のソースコード②で発生している事象は

例外がスローされました: 'System.ComponentModel.Win32Exception' (System.dll の中)
System.ComponentModel.Win32Exception: '32 ビット プロセスは、64 ビット プロセスのモジュールにアクセスできません。'

となり、そもそもプロセス終了の処理を通りません。

該当のソースコード③で発生している事象は
②と同じ

該当のソースコード

C#

1//https://dobon.net/vb/dotnet/process/getprocesses.html 2//上記「Processクラスを使用した方法」を参照 3 4//上記を参照し、正常にすべてのプロセスを取得できているのを確認したので、トライの中をif文に書き換えました。 5 6//試したコード 7//ローカルコンピュータ上で実行されているすべてのプロセスを取得 8System.Diagnostics.Process[] ps = 9 System.Diagnostics.Process.GetProcesses(); 10 11foreach (System.Diagnostics.Process p in ps) 12{ 13 try 14 { 15 if (p.MainModule.FileName.Contains(指定文字列)) 16 { 17 p.Kill(); 18 } 19 } 20 catch (Exception ex) 21 { 22 //参照できない場合などは何もしない 23 } 24}

C#

1//https://dobon.net/vb/dotnet/process/getprocessesbywindowtitle.html 2//上記「Process.MainWindowTitleを使用する方法」を参照 3 4//上記を参照し、MainWindowTitleをMainModule.FileNamに変更しました。メソッドの型や不要なリスト等は削除してます。 5 6//試したコード 7 public void GetProcessesByFileName( 8 string searchstring) 9 { 10 //すべてのプロセスを列挙する 11 foreach (System.Diagnostics.Process p 12 in System.Diagnostics.Process.GetProcesses()) 13 { 14 try 15 { 16 //指定された文字列がMainModuleのFileNameに含まれているか調べる 17 if (0 <= p.MainModule.FileName.IndexOf(searchstring)) 18 { 19 //含まれていたら、プロセス終了 20 p.Kill(); 21 } 22 } 23 catch 24 { 25 26 } 27 28 } 29 }

C#

1//https://dobon.net/vb/dotnet/process/getprocessesbyfilename.html 2//上記「ProcessModule.FileNameを使用して探す」を参照 3 4//上記を参照し、以下の文を削除、メソッドの型や不要なリスト等は削除してます。 5//削除した箇所 ファイル名の部分を取得する fileName = System.IO.Path.GetFileName(fileName); 6 7//試したコード 8 public void GetProcessesByFileName(string searchFileName) 9 { 10 searchFileName = searchFileName.ToLower(); 11 12 //すべてのプロセスを列挙する 13 foreach (System.Diagnostics.Process p 14 in System.Diagnostics.Process.GetProcesses()) 15 { 16 string fileName; 17 try 18 { 19 //メインモジュールのパスを取得する 20 fileName = p.MainModule.FileName; 21 } 22 catch (System.ComponentModel.Win32Exception) 23 { 24 //MainModuleの取得に失敗 25 fileName = ""; 26 } 27 if (0 < fileName.Length) 28 { 29 30 //探しているファイル名が含まれていた場合、プロセス終了 31 if (searchFileName.Equals(fileName.ToLower())) 32 { 33 p.Kill(); 34 } 35 } 36 } 37 38 }

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

上記記載のエラー等で実行したい終了の処理が通りませんでした。

補足

visualstudio(最新):Windowsフォーム
言語:C#

文章も長くなってしまったため要領を得ない場合はすいません、
追加情報等必要あれば記載しますのでよろしくお願いします!

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

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

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

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

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

otn

2024/11/24 12:43

お書きの状況であれば、「目的プロセスと、その子孫プロセスを全部終了する」で良い気もしますが、それでは駄目な理由があると言うことでしょうか? (「AがBを起動するが、BはCを起動してすぐ終了するため、CはAの子孫にならない」などあるのか?)
otn

2024/11/24 12:57

> '32 ビット プロセスは、64 ビット プロセスのモジュールにアクセスできません。' といいエラーが出ることについての見解はどうでしょうか? 何が32で何が64ですか?お書きのC#プログラムを32bitプログラムとして作っちゃったということですかね? あと、デバッグ中は例外の捕捉はやめた方が良いと思います。捕捉後にデフォルトの例外処理と同レベルの詳細な情報を出すのならいいのですが。
kikukiku

2024/11/25 03:57

killは最終手段とした方が良いと思います。 killされる側は何らかの処理中である場合もあるので。 本来ならば、終了させたいプロセスに対して、終了要求イベントなどを送って それを受け取ったプロセスが自身でプロセスを終了させることが望ましいです。 そのようにできない理由はありますか?
kikukiku

2024/11/25 07:22

>そもそもプロセス終了の処理を通りません。 kill以外で例外が発生しているということですか?
nururi

2024/11/25 08:05

なんかx64でビルドすれば問題なさそうな気もします。
kikukiku

2024/11/25 08:13

③の方法が正しいようです。 メインモジュールと紐づけられていないプロセスの場合や、 取得する権限がない場合に、 p.MainModule.FileNameを取得時にエラーになるとのこと。 今回killしたいexeは、上記以外のexeであれば問題なく取得できると思いますので 例外が発生したプロセスを無視しても、問題ないのではないかと思います。
kikukiku

2024/11/25 08:30

32bitビルドと、64bitビルドを試してみました。 32bitビルドの場合、6個取得できた。 64bitビルドの場合、80個ぐらい取得できました。 それぞれ比較してみたところ、重複するプロセスもありました。 よって全部リストアップするためには、32bitビルドと64bitビルドの両方が 必要みたいです。 ほぼ、64bitビルドだけで用が済みそうですが。
mysknj

2024/11/25 17:00 編集

otnさん >「目的プロセスと、その子孫プロセスを全部終了する」 そんなやり方があるのですね、そもそもそれを知らなかったのもありますが 今回実行したexeの中には指定したexeを実行後に、さらに下層のフォルダのexeを開き、最初に実行したexeが既に終了しているという挙動をしているため、このような処理をしようとしています。 ※当初の説明に抜けがありすいません。 この場合って最終的に開いたプロセスは最初に開いたプロセスの子プロセスにはならないのでしょうか? >何が32で何が64ですか?お書きのC#プログラムを32bitプログラムとして作っちゃったということですかね? すいません、知識不足でその辺が良く分かっていません。 kikukikuさん >killは最終手段とした方が良いと思います。 今回作りたいものが対象を強制的に終了させたい(KILLされる側のデータの考慮等はしない) のでこのような処理をしようとしています! >kill以外で例外が発生しているということですか? そうです、killの手前のif文でエラーが出てkillまで到達してないようです。 nururiさん >なんかx64でビルドすれば問題なさそうな気もします。 その辺の知識がないので色々確認してみましたが、プロパティ>ビルドタブの中の 対象プラットフォームらへんを弄ればよいのでしょうか? 元々が 対象プラットフォーム:「Any CPU」 「32ビットを選ぶ(P)」にチェックが入っていたので 以下2パターンを試しましたが、結果は同じくでした。(的外れな事をしていたらすいません) ▼パターン① 対象プラットフォーム:「Any CPU」を選択 「ネイティブARM64を優先する(P)」にチェック ▼パターン② 対象プラットフォーム:「×64」を選択
mysknj

2024/11/25 10:02

kikukikuさん >③の方法が正しいようです。 >今回killしたいexeは、上記以外のexeであれば問題なく取得できると思います 上記以外のexeのはずですが、なぜかkillできません… >32bitビルドと、64bitビルドを試してみました。 >よって全部リストアップするためには、32bitビルドと64bitビルドの両方が必要みたいです。 こちらって一個前のコメントに記載してるようなプロパティ>ビルドタブの中の対象プラットフォーム らへんを弄ればよいのでしょうか?そこは64ビットぽい設定に変えましたが、結果は同じくでした。 また、両方の設定が可能なのでしょうか? 知識不足ですいません。
mysknj

2024/11/25 11:39 編集

kikukikuさん すいません、単純なミスでした。 「指定した文字列がファイルパスに含まれる場合」という条件がしたかったにもかかわらず 完全一致の条件文で実行してました。以下の通りをして解決しました。 kikukikuさんのコメントでいろんな気づきがありましたので、ベストアンサーに選びたいので 回答に記載していただけるとありがたいです。 public void GetProcessesByFileName(string searchFileName) { searchFileName = searchFileName.ToLower(); //すべてのプロセスを列挙する foreach (System.Diagnostics.Process p in System.Diagnostics.Process.GetProcesses()) { string fileName; try { //メインモジュールのパスを取得する fileName = p.MainModule.FileName; fileName = fileName.ToLower(); } catch (System.ComponentModel.Win32Exception) { //MainModuleの取得に失敗 fileName = ""; } if (0 < fileName.Length) { //探しているファイル名が含まれていた場合、プロセス終了 if (fileName.Contains(searchFileName)) { p.Kill(); } } } }
kikukiku

2024/11/25 23:47

ベストアンサーが欲しいわけではないので、 自身でどのように解決したのかを回答に記述して ベストアンサーにし、自己解決としてください。
guest

回答1

0

Win32 Job Objectを作って子Processを属させればいい。
孫は自動的にそのjobに属するので。

https://www.meziantou.net/killing-all-child-processes-when-the-parent-exits-job-object.htm

投稿2024/11/25 08:00

matukeso

総合スコア1681

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

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

mysknj

2024/11/25 10:07

matukesoさん NuGetでMeziantou.Framework.Win32.JobsをインストールすればWin32 Job Objectが作れて、 それを使えば対象の子孫プロセスまでkillできるということでしょうか。 ちょっと難しそうですが試してみます。 分からないことがあったら再度質問させていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.34%

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

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

質問する

関連した質問