我试图找到一种方法来从命令提示符中获取我自己的PID(以供以后在bat脚本中使用),到目前为止,我发现的唯一有用的方法是从此处使用getpids.exe:http : //www.scheibli.com/ projects / getpids / index.html但我正在寻找“内置”到Windows的命令
编辑:我正在寻找一种“项目符号证明”的方式-没有关于我的过程是唯一的cmd.exe或任何假设
我试图找到一种方法来从命令提示符中获取我自己的PID(以供以后在bat脚本中使用),到目前为止,我发现的唯一有用的方法是从此处使用getpids.exe:http : //www.scheibli.com/ projects / getpids / index.html但我正在寻找“内置”到Windows的命令
编辑:我正在寻找一种“项目符号证明”的方式-没有关于我的过程是唯一的cmd.exe或任何假设
Answers:
由于没有其他解决方案是防弹和内置的,因此我认为我将提供以下解决方案,但是请注意,您需要以某种方式解析/保存结果:
title mycmd
tasklist /v /fo csv | findstr /i "mycmd"
microseconds
在这种情况下,可能(未经深度测试)会得到更精确的时间戳(包括,而不是像%time%中那样为1/100秒),该时间戳会更可靠:wmic os get LocalDateTime
(YearMonthDayHourMinuteSecond.Microsecond + Timezone)。除非调度程序能够在完全相同的微秒内运行两件事...
我相信以下内容是防弹的,只要用户可以访问WMIC和TEMP即可指向用户具有写权限的有效路径。这是http://www.dostips.com/forum/viewtopic.php?f=3&t=6133上的一些协作工作的最终结果。
@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
该脚本在临时文件上建立排他锁,该文件将当前时间合并到名称中。仅当两个类似的命名批处理进程试图在相同的0.01秒时间间隔内获取PID时,才会发生冲突,在这种情况下,只有一个成功。
任何失败的进程都将反复循环返回,并使用新的锁定文件路径再试一次,直到成功为止。
锁定文件的完整路径将转换为可在WMIC查询中使用的唯一ID。WMIC在FOR / F命令中运行,这意味着它在子cmd.exe进程中运行。这就是为什么要检索cmd.exe进程的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"
因为窗口标题实际上包含当前命令(因此,如果您尝试完全匹配它,它将继续存在)。
使用PowerShell + WMI:
powershell (Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId
pwsh -noprofile -c "(Get-Process -Id $PID).Parent.Id"
如果您知道只有一个cmd.exe在运行,则可以通过以下方式获取PID:
for /F "tokens=1,2" %%i in ('tasklist /FI "IMAGENAME eq cmd.exe" /fo table /nh') do set pid=%%j
echo %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不会有大于18100的PID,因此请检查PID2是否大于8100,以便我们知道它是4位还是5位数字
情况1:像17504这样的5位数PID的PID1值17504和PID2值1750,因此我们使用PID1
情况2:像8205这样的4位数PID的PID1值是8205“,而PID2值是8205,所以我们使用PID2
情况3:像4352这样的4位数PID的PID1值是4352“,PID2值是4352,所以我们使用PID2