2015-03-04 4 views
0

Это должно быть довольно просто, но я не смог его найти.Получение Pid из cmd во время запуска командного скрипта

Если я запускаю некоторый пакетный скрипт в cmd, как мне получить идентификатор процесса хостинга cmd?

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

Я нашел много решений, которые используют tasklist и имя фильтрации, но я считаю, что эта работа для выигранное `t меня, так как там может быть запущено множество экземпляров ЦМД.

Опять же, я хотел бы иметь простое элегантное и пуленепробиваемое решение.

Спасибо.

+0

Ну, это не просто, но я думаю (это пуленепробиваемый) (http://stackoverflow.com/a/27514649/1683264) в любом случае. – rojo

+0

Почему это так сложно на Windwos :(Это такая простая и обычная вещь. – steavy

+0

Было бы неплохо, если бы среда cmd была подвергнута воздействию собственной информации процесса через переменные среды, не так ли? В любом случае, что ваша цель в получении ПИД-регулятора текущей консоли? Если вы используете его для блокировки процесса, [для этого есть, вероятно, лучшие решения] (http://stackoverflow.com/a/27756667/1683264). – rojo

ответ

1

Здесь тема обсуждалась ->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); 
+0

Просьба указать основные части ответа из ссылочной ссылки (ссылок), так как ответ может стать недействительным, если связанные страницы изменились. – DavidPostill

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 устанавливает файл программы (скомпилированный JScript) в той же папке, что и пакетного сценария.

На моей машине мой чистый пакет getPID работает на 20% быстрее, чем exp npocmaka! Это связано с тем, что exe сначала определяет свой собственный PID процесса, который занимает значительное время, прежде чем он использует WMI для определения желаемого родительского PID. Мой скрипт генерирует уникальный идентификатор (намного быстрее), который включается в вызов WMIC, который определяет желаемый родительский PID.

В обоих решениях основная часть времени проводится в WMI, где он определяет родительский PID определенного процесса.

Смежные вопросы