Я вважаю, що наступне є куленебезпечним, за умови, що користувач має доступ до 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
Сценарій встановлює ексклюзивний замок у тимчасовому файлі, який включає в себе ім'я поточного часу. Зіткнення може відбутися лише в тому випадку, якщо два подібні пакетні процеси намагаються отримати PID протягом одного і того ж інтервалу 0,01 секунди, і в цьому випадку лише один матиме успіх.
Будь-який процес, який завершився невдачею, буде повторно циклічно повертатися та повторити спробу з новим контуром файлу блокування, поки це не вдасться.
Повний шлях до файлу блокування перетворюється на унікальний ідентифікатор, який може бути використаний у WMIC-запиті. WMIC запускається в команді FOR / F, що означає, що він працює в дочірньому процесі cmd.exe. Ось чому отримується ParentProcessID процесу cmd.exe.