Este é um trabalho SetMyPrio.bat
MyPrio.bat
que você pode usar de outro para definir a prioridade do seu lote. Se você copiá-lo para um diretório em seu %PATH%
, poderá chamá-lo sempre que precisar, etc., como de costume. Graças ao TOOGAM , isso me deu as ferramentas e o método para escrever isso. A variável UniqueString
garante que o processo identificado seja exatamente o que você precisa e não qualquer outra instância do seu lote (cenário improvável, mas possível).
@echo off
GOTO :EndOfReminder
<HELP>
USAGE:
From any batch file or command prompt, write
CALL MyPrio [/?|/h] [<priority>|get]
to set the priority of the caller cmd. Default for <priority> is idle.
/?, /h This help.
<priority> If you want your priority change to
idle -- no parameter, 64, idle or "idle"
below normal -- 16384 or "below normal"
normal -- 32, normal or "normal"
above normal -- 32768 or "above normal"
high priority -- 128 or "high priority"
real time -- 256, realtime or "realtime"
get Returns current priority as errorlevel
TO DO
- Parameter error control.
- Support for Unicode characters in help.
</HELP>
:EndOfReminder
setlocal
set Priority=%~1
if /I ["%Priority%"]==["/h"] ( call :PrintHelp & exit /b )
if ["%Priority%"]==["/?"] ( call :PrintHelp & exit /b )
set UniqueString=%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%
if ["%Priority%"]==["get"] for /f "usebackq tokens=2 delims==" %%a in ('wmic Process WHERE "name='cmd.exe' AND CommandLine LIKE '%%%UniqueString%%%'" Get Priority /format:LIST') do exit /b %%a
if not defined Priority set Priority=idle
for /f "usebackq tokens=2 delims==" %%a in ('wmic Process WHERE "name='cmd.exe' AND CommandLine LIKE '%%%UniqueString%%%'" Get ParentProcessID /format:LIST') do set myPID=%%a
wmic process where "ProcessId='%myPID%'" CALL setpriority "%Priority%" > nul 2>&1
endlocal
goto :eof
:PrintHelp
setlocal DisableDelayedExpansion
call :eln 0
set "levelerror=^%%errorlevel^%%"
for /F "delims=" %%a in ('find /v /n "" "%~f0"') do (
set "line=%%a"
REM We store errorlevel in tmpel because setlocal will set errorlevel to 0...
call set tmpel=%levelerror%
setlocal EnableDelayedExpansion
REM ... and now we restore it
REM %levelerror% was expanded to %errorlevel% before running the iteration
REM and the CALL SET allows actual errorlevel be stored in tmpel
REM Finally, we set errorlevel again
call :eln !tmpel!
set "line=!line:*]=!"
if /i "!line!"=="</HELP>" exit /b 0
if errorlevel 1 echo(!line!
if /i "!line!"=="<HELP>" call :eln 1
REM errorlevel is the only value that survives the following endlocal
endlocal
)
exit /b 1
:eln
REM Sets errorlevel to %1
exit /b %1
Editar (2018-06-12)
- Alterou o nome para MyPrio , opções adicionadas
/?
,/h
eget
. - Opções
/?
e/h
imprimem o texto que você escreve no lembrete entre<HELP>
e</HELP>
. Este método pode ser reutilizado em qualquer outro lote que você precise.
Se você fizer uma chamada para MyPrio.bat
no início de um lote, sempre que iniciar, independentemente de uma linha de comando ou arrastando e soltando arquivos do Windows Explorer (que se tornam parâmetros), todas as partes dele (e processos filho) será executado com a prioridade desejada.
Por exemplo:
@echo off
call MyPrio
REM Here comes a set of commands that will run with idle priority.
call MyPrio normal
REM Here may come some interactive part to request information needed to continue.
call MyPrio
REM Back to idle (or put any other priority you prefer).
call MyPrio normal
REM You may want to set the priority to normal at the end just in case you call the batch from a command line.
COMENTÁRIOS
Eu fiz um lote chamado PrioTest.bat
para testar MyPrio.bat
com todas as opções possíveis e as ordenei para que qualquer chamada altere a prioridade para outra diferente. Eu fiz uma sub-rotina ( :test1
) que:
1. Obtém a prioridade atual e salva em myPrioBefore
.
2. Chama MyPrio
com o parâmetro de teste.
3. Obtém nova prioridade e salva em myPrioAfter
.
4. Inicia um ping -t localhost
oculto.
5. Obtém prioridade e PID do processo ping
e os salva em
pingPrio
e pingPID
.
6. Imprime os valores de myPrioBefore
, a chamada para MyPrio
,
myPrioAfter
e pingPrio
.
7. Elimina o ping
iniciado (tendo certeza de que não é outro).
@echo off
setlocal
set UniqueString=%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%
for /f "usebackq tokens=2 delims==" %%a in ('wmic Process WHERE "name='cmd.exe' AND CommandLine LIKE '%%%UniqueString%%%'" Get ParentProcessID /format:LIST') do set myPID=%%a
for %%a in (64 16384 32 32768 128 256 idle "below normal" none normal "idle" "normal" "above normal" realtime "high priority" "realtime") do call :test1 %%a
CALL MyPrio normal
endlocal
goto :eof
:test1
for /f "usebackq tokens=2 delims==" %%b in ('wmic Process WHERE "ProcessID='%%myPID%%'" Get Priority /format:LIST') do set myPrioBefore=%%b
if [%1]==[none] ( call MyPrio ) else ( call MyPrio %1 )
for /f "usebackq tokens=2 delims==" %%b in ('wmic Process WHERE "ProcessID='%%myPID%%'" Get Priority /format:LIST') do set myPrioAfter=%%b
start "" /b ping -t localhost > nul
for /f "usebackq tokens=2 delims==" %%b in ('wmic Process WHERE "name='ping.exe' AND ParentProcessID='%%myPID%%'" Get Priority /format:LIST') do set pingPrio=%%b
for /f "usebackq tokens=2 delims==" %%b in ('wmic Process WHERE "name='ping.exe' AND ParentProcessID='%%myPID%%'" Get ProcessID /format:LIST') do set pingPID=%%b
echo myPrioBefore==%myPrioBefore% / CALL MyPrio %1 / myPrioAfter==%myPrioAfter% / pingPrio==%pingPrio%
taskkill /f /pid %pingPID% > nul
exit /b
Esta é a saída do lote do testador:
myPrioBefore==4 / CALL MyPrio 64 / myPrioAfter==4 / pingPrio==4
myPrioBefore==4 / CALL MyPrio 16384 / myPrioAfter==6 / pingPrio==6
myPrioBefore==6 / CALL MyPrio 32 / myPrioAfter==8 / pingPrio==8
myPrioBefore==8 / CALL MyPrio 32768 / myPrioAfter==10 / pingPrio==8
myPrioBefore==10 / CALL MyPrio 128 / myPrioAfter==13 / pingPrio==8
myPrioBefore==13 / CALL MyPrio 256 / myPrioAfter==13 / pingPrio==8
myPrioBefore==13 / CALL MyPrio idle / myPrioAfter==4 / pingPrio==4
myPrioBefore==4 / CALL MyPrio "below normal" / myPrioAfter==6 / pingPrio==6
myPrioBefore==6 / CALL MyPrio none / myPrioAfter==4 / pingPrio==4
myPrioBefore==4 / CALL MyPrio normal / myPrioAfter==8 / pingPrio==8
myPrioBefore==8 / CALL MyPrio "idle" / myPrioAfter==4 / pingPrio==4
myPrioBefore==4 / CALL MyPrio "normal" / myPrioAfter==8 / pingPrio==8
myPrioBefore==8 / CALL MyPrio "above normal" / myPrioAfter==10 / pingPrio==8
myPrioBefore==10 / CALL MyPrio realtime / myPrioAfter==13 / pingPrio==8
myPrioBefore==13 / CALL MyPrio "high priority" / myPrioAfter==13 / pingPrio==8
myPrioBefore==13 / CALL MyPrio "realtime" / myPrioAfter==13 / pingPrio==8
Como você pode ver, myPrioAfter
não corresponde ao solicitado na chamada e às vezes , a prioridade de ping
não é igual ao pai cmd
, portanto, deve haver mais para os valores (olhe para a quinta linha: a prioridade atual é 10, você solicita 128, a nova prioridade é 13 e o processo filho '8, desculpe?). Além disso, realtime
parece não ter efeito (é necessário assumir os direitos de administrador).