在运行批处理脚本时获取cmd的Pid

时间:2015-03-04 18:21:40

标签: batch-file process cmd echo

这应该很简单但我找不到它。

如果我在cmd中运行一些批处理脚本,我如何获取托管cmd的进程ID?

set currentCmdPid= /* some magic */
echo %currentCmdPid%

我找到了许多使用tasklist和名称过滤的解决方案,但我相信这对我来说不起作用,因为可以启动许多cmd实例。

同样,我想要一些简单优雅且防弹的解决方案。

感谢。

3 个答案:

答案 0 :(得分:2)

以下是my pure batch script version生成的same DosTips discussion and collaborative effort that npocmaka referenced

@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

npocmaka's solution将exe文件(已编译的JScript)安装在与批处理脚本相同的文件夹中。

在我的机器上,我的纯批量getPID运行速度比npocmaka的exe快20%!这是因为在使用WMI确定所需的父PID之前,exe首先确定自己的进程PID,这需要很长的时间。我的脚本生成一个唯一的ID(更快),它被合并到确定所需父PID的WMIC调用中。

在这两种解决方案中,大部分时间都花在WMI中,它确定特定进程的父PID。

答案 1 :(得分:1)

此处讨论的主题 - &gt; http://www.dostips.com/forum/viewtopic.php?p=38870

这是我的解决方案:

@if (@X)==(@Y) @end /* JScript comment
@echo off
setlocal

for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
   set "jsc=%%v"
)


if not exist "%~n0.exe" (
   "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0" 
)

%~n0.exe

endlocal & exit /b %errorlevel%

*/


import  System;
import  System.Diagnostics;
import  System.ComponentModel;
import  System.Management;

var myId = Process.GetCurrentProcess().Id;
var query = String.Format("SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = {0}", myId);
var search = new ManagementObjectSearcher("root\\CIMV2", query);
var results = search.Get().GetEnumerator();
if (!results.MoveNext()) {
   Console.WriteLine("Error");
   Environment.Exit(-1);
}
var queryObj = results.Current;
var parentId = queryObj["ParentProcessId"];
var parent = Process.GetProcessById(parentId);
Console.WriteLine(parent.Id);

答案 2 :(得分:0)

为了获取 cmd PID,我从 cmd 运行 powershell 并获取父进程 ID——这将是 cmd PID。脚本获取父级的父级(因为 FOR /F 调用另一个 cmd.exe)。

FOR /F "tokens=* USEBACKQ" %%F IN (`powershell  -c "(gwmi win32_process | ? processid -eq ((gwmi win32_process | ? processid -eq  $PID).parentprocessid)).parentprocessid"`) DO (
  SET PCT_CleanAfterPID=%%F
)

ECHO %PCT_CleanAfterPID%