[BluePrism]プロセス名からプロセスIDとウィンドウ名を取得するオブジェクトを書きました。 #blueprism

# 2023年追記
「Utility - Environment」の「Read Memory Stats」でこれと同じようなことができるっぽいです。
出来合いのアクションがあったのか……。

# これを書いた理由

たとえばブラウザが複数枚開いていたとして、どのブラウザをアタッチして処理に使うか、というのは
UiPathだったらブラウザ変数で管理すればいいのですよね。
しかしBlue Prismにはブラウザ変数がないので、どうしよう……と試行錯誤していたときに書いたものです。
ずいぶん前に書いて死蔵してたものなので、こちらに記録しておこうかなと……。

# プロセスIDを取得するには
まずプロセスIDって何か（ごめんなさい私がレベル低いのでそこからです……）というのは
[Process Explorer(Microsoftの)](https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer)
っていうのがあって、これで詳しいプロセス名とかプロセスIDとか見ることができて便利です。
こんなやつ
![processexplorer.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/94bfa3cc-b2a5-f81f-4ef5-da5dce9efb2d.jpeg)
これで見ると、同じアプリとかブラウザが複数起動していてもプロセスIDが異なるので、プロセスIDで一意に指定できることがわかります。

そのプロセスIDを取得するのは
[特定のexeのPIDを取得する方法について(teratail)](https://teratail.com/questions/67402)

プロセス名からプロセスを取得するのは
[指定した名前のすべてのプロセスを取得する](https://dobon.net/vb/dotnet/process/getprocessesbyname.html)

コードステージでコレクションをどうにかするのは
[How to store data into a collection form string in Blue Prism(stackoverflow)](https://stackoverflow.com/questions/49737477/how-to-store-data-into-a-collection-form-string-in-blue-prism)

これのなかに書いてあるGetTypeとかDataTypeっていうのは何かっていうと
[DataColumn.DataType プロパティ](https://docs.microsoft.com/ja-jp/dotnet/api/system.data.datacolumn.datatype?view=netframework-4.8)
名前空間はデフォルトで設定されているSystem.Dataなので、今回は追加で設定するものはなさげ。

# これらを踏まえて作ったもの

入力引数がProcessName（テキスト）
出力引数がProcesses（コレクション）
です。

- まず、コレクションに列を2列（プロセスID、ウィンドウの名前）作成して
- そのプロセス名のプロセスを全部取得し
- 取得したプロセスのIDと名前を順にコレクションに格納

という手順です。

```c#
Processes = new DataTable();

Processes.Columns.Add(new DataColumn("PID", typeof(int)));
Processes.Columns.Add(new DataColumn("WindowTitle", typeof(string)));

foreach (var p in System.Diagnostics.Process.GetProcessesByName(ProcessName))
{
    try
    {
        Processes.Rows.Add(new object[] {p.Id, p.MainWindowTitle});
    }
    catch (Exception) { }
}

```

# 添削していただきました！
[たかぎさん](https://qiita.com/tkgsn146)ありがとうございます！大好き！

## 前半（出力用コレクションの準備）

### 添削前
```c#
DataColumn col1 = new DataColumn();
col1.DataType = System.Type.GetType("System.Int32");
col1.ColumnName = "PID";
Processes.Columns.Add(col1);

DataColumn col2 = new DataColumn();
col2.DataType = System.Type.GetType("System.String");
col2.ColumnName = "WindowTitle";
Processes.Columns.Add(col2);
```

### 添削後
```c#
Processes.Columns.Add(new DataColumn("PID", typeof(int)));
Processes.Columns.Add(new DataColumn("WindowTitle", typeof(string)));
```
### 添削内容
列追加が1行ずつになった！


添削前のコードのお手本になったのは、これです。
[DataTable クラス](https://docs.microsoft.com/ja-jp/dotnet/api/system.data.datatable?view=netframework-4.8)

```c#
// Create a new DataTable.
System.Data.DataTable table = new DataTable("ParentTable");
// Declare variables for DataColumn and DataRow objects.
DataColumn column;
DataRow row;

// Create new DataColumn, set DataType, 
// ColumnName and add to DataTable.    
column = new DataColumn();
column.DataType = System.Type.GetType("System.Int32");
column.ColumnName = "id";
column.ReadOnly = true;
column.Unique = true;
// Add the Column to the DataColumnCollection.
table.Columns.Add(column);
```

この添削後に出てくるtypeofっていうのは
[C#で型を判別するtypeofとis演算子](https://araramistudio.jimdofree.com/2018/09/21/c-%E3%81%A7%E5%9E%8B%E3%82%92%E5%88%A4%E5%88%A5%E3%81%99%E3%82%8Btypeof%E3%81%A8is%E6%BC%94%E7%AE%97%E5%AD%90/)
typeofはJavaScriptにもあるから知ってる！書き方違うけど！
[typeof(MDN)](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/typeof)


## 後半（プロセスを取得して出力用コレクションに格納）

### 添削前
```c#
//そのプロセス名のプロセスを全部取得し
System.Diagnostics.Process[] ps = System.Diagnostics.Process.GetProcessesByName(ProcessName);

//取得したプロセスのIDと名前を順にコレクションに格納
foreach (System.Diagnostics.Process p in ps)
{
	DataRow row = Processes.NewRow();
	Processes.Rows.Add(p.Id,p.MainWindowTitle);
}

```

### 添削後

```c#
foreach (var p in System.Diagnostics.Process.GetProcessesByName(ProcessName))
{
	try
	{
		Processes.Rows.Add(new object[] {p.Id, p.MainWindowTitle});
	}
	catch (Exception) { }
}
```

### 添削内容
行追加して、追加した行に値を設定して、って2行でやってたところが1行になりました。
あと、まずプロセスを取得して、それから取得したプロセスに対してforeachをまわす、と書いていたところが
1個にまとめられました。

それからエラーハンドリングも足されましたね。
ぶっちゃけ、落ちたらどのみちオブジェクトから例外スローされて返るからいっかと手を抜いてました（テヘ



# 終わりです（あんまり終わりではない）

コレクションに予め列を作っておけばコードステージで列を追加することないんじゃないかと思って試したのですが、そこはまだうまくいかず……
やりかたを教えてください。