コマンドプロンプト(後でbatスクリプトで使用するため)から自分のPIDを取得する方法を見つけようとしています。
これまでのところ、私が見つけた唯一の便利な方法はgetpids.exe
ここから: http://www.scheibli.com/projects/getpids/index.html ですが、Windowsに「組み込まれている」コマンドを探しています。
「防弾」の方法を探しています。私のプロセスが唯一のcmd.exeなどであるという想定はありません。
他のソリューションはどれも完全なものではなく、組み込まれていないので、次のソリューションを提供すると思いましたが、結果を何らかの方法で解析/保存する必要があることに注意してください。
title mycmd
tasklist /v /fo csv | findstr /i "mycmd"
PowerShell + WMIの使用:
powershell (Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId
トニーロスの答えをさらに詳しく説明します。
title uniqueTitle
for /f "tokens=2 USEBACKQ" %f IN (`tasklist /NH /FI "WINDOWTITLE eq uniqueTitle*"`) Do echo %f
WINDOWTITLEフィルターを使用すると、パイプが回避されるため、forループに入れて、SETを使用して変数に割り当てることができます。
title uniqueTitle
for /f "tokens=2 USEBACKQ" %f IN (`tasklist /NH /FI "WINDOWTITLE eq uniqueTitle*"`) Do set ourPID=%f
/v
を削除すると処理が速くなり、/NH
はヘッダー行を削除します。ウィンドウのタイトルには実際に現在のコマンドが含まれているため、"uniqueTitle"
の後にワイルドカードが必要です(完全に一致させようとすると、このコマンドが繰り返し実行されます)。
ユーザーがWMICにアクセスでき、TEMPがユーザーが書き込み権限を持っている有効なパスを指している場合、以下は完全な防御策だと思います。これは http://www.dostips.com/forum/viewtopic.php?f=3&t=61 での共同作業の最終結果です。
@echo off
:getPID [RtnVar]
::
:: Store the Process ID (PID) of the currently running script in environment variable RtnVar.
:: If called without any argument, then simply write the PID to stdout.
::
setlocal disableDelayedExpansion
:getLock
set "lock=%temp%\%~nx0.%time::=.%.lock"
set "uid=%lock:\=:b%"
set "uid=%uid:,=:c%"
set "uid=%uid:'=:q%"
set "uid=%uid:_=:u%"
setlocal enableDelayedExpansion
set "uid=!uid:%%=:p!"
endlocal & set "uid=%uid%"
2>nul ( 9>"%lock%" (
for /f "skip=1" %%A in (
'wmic process where "name='cmd.exe' and CommandLine like '%%<%uid%>%%'" get ParentProcessID'
) do for %%B in (%%A) do set "PID=%%B"
(call )
))||goto :getLock
del "%lock%" 2>nul
endlocal & if "%~1" equ "" (echo(%PID%) else set "%~1=%PID%"
exit /b
スクリプトは、現在の時刻を名前に組み込んだ一時ファイルに排他ロックを確立します。同じ名前の2つのバッチプロセスが同じ0.01秒の時間間隔内にPIDを取得しようとした場合にのみ、衝突が発生する可能性があります。この場合、1つだけが成功します。
失敗したプロセスはループバックを繰り返し、成功するまで新しいロックファイルパスで再試行します。
ロックファイルへのフルパスは、WMICクエリで使用できる一意のIDに変換されます。 WMICはFOR/Fコマンド内で実行されます。つまり、WMICは子cmd.exeプロセスで実行されます。そのため、cmd.exeプロセスのParentProcessIDが取得されます。
実行中のcmd.exeが1つしかないことがわかっている場合は、次の方法でPIDを取得できます。
for /F "tokens=1,2" %%i in ('tasklist /FI "IMAGENAME eq cmd.exe" /fo table /nh') do set pid=%%j
echo %pid%
これでうまくいくはずです:
タスクリスト/ v
Imagename "notepad.exe"のPIDを検索する場合は、次のコードが機能します。
for /F "tokens=1,2" %i in ('tasklist') do (
if "%i" equ "notepad.exe" (set x=%j)
)
echo %x%
Windows 2003リソースキットをお持ちの場合は、qgrepにプッシュして、必要な行だけを取得します。次に、ここからpidを抽出できます(これは、一度に実行するcmdが1つだけであると想定しています)。
tasklist /v | qgrep cmd
cmd.exe 2040 RDP-Tcp#447 0 1,804 K Running MACHINE\Administrator 0:00:00 Command Prompt
これを見てみましょう 小さなバッチトリック 。 cmdのタイトルを特別な値に設定し、タスクリストを使用してそれを見つけます。発明
\\グレッグ
getcmdPid.bat で試すことができます-これはbatスクリプトに埋め込まれた自己コンパイルされた.netアプリケーションであり、PIDをエラーレベルとして返します。
call getcmdPid
echo %errorlevel%
これはIS OPEN CMDのプロセスIDを取得する短い方法
tasklist /v /fi "imagename EQ cmd.exe" /FO LIST | FIND "PID:"
この回答では、プロセスIDのみが提供され、上位の回答に含まれるその他の情報は提供されません。
title mycmd
tasklist /v /fo csv | findstr /i "mycmd" > PIDinfo.txt
set /p PIDinfo=<PIDinfo.txt
set PID1=%PIDinfo:~11,5%
set PID2=%PIDinfo:~11,4%
if %PID2% gtr 8100 (
set PID=%PID2%
) else (
set PID=%PID1%
)
echo %PID%
説明:
-cmd.exeのPIDが18100を超えることはないので、PID2が8100を超えているかどうかを確認して、4桁か5桁かを確認します。
ケース1:17504のような5桁のPIDのPID1値は17504で、PID2値は1750なので、PID1を使用します。
ケース2:8205のような4桁のPIDは、8205 "のPID1値と8205のPID2値を持つため、PID2を使用します。
ケース3:4352のような4桁のPIDは、4352のPID1値と4352のPID2値があるため、PID2を使用します。