何気に.NET Framework/.NET Coreには外部プロセスのコマンドラインを取得する方法が無く、このため、PowerShellからコマンドラインを取得しようとする場合少し手間をかけてやる必要があります。
PowerShellで外部プロセスのコマンドラインを取得する
簡単な関数Get-ProcessCommandline
を作ってGistに上げました。
使用例と併せてご覧ください。
厳密に対応バージョンを考慮していませんが、Windows PowerShell、PowerShell Core両方の大抵の環境で動くはずです。
簡単な解説
各プラットフォーム毎の簡単な解説を補足しておきます。
Windowsの場合
Windowsにおいて外部プロセスのコマンドラインを取得するには、ReadProcessMemoryなどのプロセス情報を読み取るWin32 APIを使うかWMIを使う必要があります。
PowerShellからであればWMIを扱うほうが圧倒的に楽なので先述の関数でもWMIを使っています。
Win32_Process
クラスにCommandLine
というズバリなプロパティがあるのでこれを取得するだけでOKです。
# Windowsでは Win32_Process クラスの CommandLine プロパティからコマンドラインを取得可能 $proc = Get-WmiObject -Class Win32_Process -Filter "ProcessId = $Id" -Property "ProcessId", "CommandLine" if ($null -eq $proc) { return "" } return $proc.CommandLine # PowerShell Core なら Get-CimInstance を使う $proc = Get-CimInstance -Class Win32_Process -Filter "ProcessId = $Id" -Property "ProcessId", "CommandLine" if ($null -eq $proc) { return "" } return $proc.CommandLine
Linuxの場合
Linuxの場合プロセスの情報を/proc/
から取得することができます。
プロセスのコマンドラインは/proc/[プロセスID]/cmdline
に記述されているのでGet-Content
で内容を読み取ってやればOKです。
注意すべきところはコマンドラインのデリミタがヌル文字(\0
)である点くらいでしょうか。
# Linuxでは /proc/[プロセスID]/cmdline からコマンドラインを取得可能 if (-not (Test-Path -LiteralPath "/proc/$Id")) { return "" } return @(Get-Content -LiteralPath "/proc/$Id/cmdline")[0] -replace "\0", " "
macOSの場合
残念ながらmacOSには/proc/
が存在せずLinuxと同じ様にはいきません。
macOSのシステムプログラミングには全く詳しくないため大した調査は出来なかったのですが、
を見る限りではCで頑張らないとダメな様です。
ちょっと本末転倒な感じもありますが、PowerShellからだとps
コマンドの結果を抜くのが一番手っ取り早く確実です。
(これならはじめからpsコマンドだけで良いのでは?というお気持ちです...)
psコマンドで特定の要素だけ取得するには-o
オプションを、取得結果からカラムヘッダーを除外するには=
をつけてやればよいため、ps -o commnand=
の様に指定してやればコマンドラインを取得できます。
# macOSの場合は psコマンドを使ってコマンドラインを取得可能 return (/bin/ps -o command= -p $Id)