2015-04-01 5 views
4

Последние несколько дней я работал над сценарием, который, как я думал, будет довольно простым, но, похоже, нет, и я понимаю, почему. Моя проблема в том, как обойти это.Как я могу убить все cmd.exe, кроме того, что в данный момент выполняется из пакета?

Пакетный сценарий мне нужно объяснил:

У меня есть сценарий, который работает в cmd.exe, который делает кучу вещей, как перемещение огромного количества файлов из места в другое. Назовите его movefile.cmd. Этот скрипт работает, но иногда он останавливается (очень редко - позволяет не вникать в почему и этот скрипт). Важно, чтобы этот скрипт всегда работал, поэтому моя идея заключалась в создании пакета, который выходит из cmd.exe, а затем снова открывает скрипт каждый час или около того. Назовём этот скрипт restartcmd.bat

прекрасно звучит просто, как я мог бы сделать это:

@echo off 

:loop 

start c:\script\movefile.cmd 

Timeout /nobreak /t 3600 

Taskkill cmd.exe 

goto loop 

Но очевидно, что это не работает, потому что мой новый сценарий также работает в cmd.exe, так что бы убить этого процесс также.

Что я пробовал:

Так что я сделал копию cmd.exe и переименовал его в dontkillthis.exe. Я запускаю dontkillthis.exe, а затем откройте restardcmd.bat от dontkillthis.exe - это работает отлично! Но я должен уметь просто dobbleclick мой скрипт вместо этого. Зачем? Поскольку он должен быть как можно более простым, и я хочу, чтобы мой restartcmd.bat находился в моей папке автозагрузки.

Я искал идеи получения точного идентификатора процесса cmd.exe и закрыл его, чтобы мой dontkillthis.exe остался, но я не могу прибить его. Пробовал все, что написано здесь how to kill all batch files except the one currently running, но я не могу заставить его работать.

Я не уверен, если я запутался или на самом деле это немного сложно сделать.

Я бы очень признателен за помощь здесь.

С наилучшими пожеланиями

MO

+0

Грязный путь: создайте копию 'cmd' как' kill-me.exe', используйте 'start kill-me c: \ script \ movefile.cmd' & then 'taskkill kill-me.exe' (Это быстрый взлом. Должны быть лучшие способы.) – anishsane

+0

[Получить идентификатор текущего cmd.exe] (https://social.msdn.microsoft.com/Forums/vstudio/en-US/270f0842-963d-4ed9-b27d-27957628004c/what -is-the-pid-of-the-current-cmdexe), тогда 'taskkill' имеет возможность фильтровать на основе' PID! = xxx' Check 'taskkill /?'. – anishsane

ответ

6

Сначала вам понадобится PID текущего экземпляра CMD. В теме есть been discussed here. Я предложу вам мое решение - getCmdPID.bat

и вот сценарий (getCmdPID должен в том же каталоге):

@echo off 

call getCmdPID 
set "current_pid=%errorlevel%" 

for /f "skip=3 tokens=2 delims= " %%a in ('tasklist /fi "imagename eq cmd.exe"') do (
    if "%%a" neq "%current_pid%" (
     TASKKILL /PID %%a /f >nul 2>nul 
    ) 
) 
+1

Npocmaka, что на самом деле (и удивительно для меня) работал как шарм! Спасибо чувак. Именно то, что я искал! Пятно на. :) – MadsTheMan

0

Было бы гораздо лучше, чтобы получить PID вашего movefile.cmd. Если вы можете изменить его, добавить title MyMoveFileProcess и получить его PID с

for /f "tokens=2" %%i in ('tasklist /v ^|find "MyMoveFileProcess"') do set PID=%%i 

Тогда вы можете убить его с taskkill /pid %pid%

вместо изменения movefile.cmd, вы также можете просто запустить его с названием:

start "MyMoveFileProcess" c:\script\movefile.cmd 
+0

Этот первый код является полным сбоем - он перечисляет все процессы cmd.exe. Конструкция принципиально ошибочна. – dbenham

+0

@dbenham да, это так (как я писал). Может быть, мне лучше удалить эту часть. – Stephan

+0

@dbenham с другой стороны: заголовок вопроса говорит «как убить всех cmd.exe, кроме ...», что я согласен, это плохой подход. – Stephan

0

Кроме того, только для информации для других. Я узнал, что можно остановить и запустить другие cmd-файлы на основе названия, что было бы альтернативой решению моего вопроса. Поэтому давайте скажем, что movefile.cmd имеет эту строку в своем скрипте: Title "movefile" («» важно). Тогда я могу написать taskkill /F /FI "WindowTitle eq Administrator: \"movefile"" /T в restartcmd.bat :)

1

Обычно с помощью следующей команды я должен быть в состоянии найти PID. К сожалению, это не случай.

title exclude &tasklist /NH /v /fo csv /FI "WINDOWTITLE ne exclude*" /FI "IMAGENAME eq cmd.exe" /FI "STATUS eq running" 

Итак, чтобы достичь своей цели, я использовал следующую команду: FIND /I "exclude" 1>NUL

@echo off 
TITLE exclude 
(for /f "usebackq tokens=*" %%a in (`tasklist /NH /v /fo csv /FI "IMAGENAME eq cmd.exe" /FI "STATUS eq running"`) do (
    (
    echo %%a | FIND /I "exclude" 1>NUL 
) || ( 
    for /f "usebackq tokens=2 delims=," %%i in (`echo %%a`) do (
     echo TASKKILL /PID %%~i /f 
    ) 
) 
) 
)>_output-taskill.txt 
TYPE _output-taskill.txt 

Другой подход, чтобы убить все процессы в одной строке является использование фильтров по команде taskkill с фильтрами должны выглядеть так:

TASKKILL /F /FI "PID ne XXXX" /FI "IMAGENAME eq cmd.exe" /IM cmd.exe 

экв (равно)

пе (не равно)

GT (больше)

л (меньше, чем)

@echo off 
TITLE exclude 
(for /f "usebackq tokens=2 delims=," %%a in (`tasklist /NH /v /fo csv /FI "IMAGENAME eq cmd.exe" /FI "STATUS eq running" ^| FIND /I "exclude"`) do (
    echo TASKKILL /F /FI "PID ne %%~a" /FI "IMAGENAME eq cmd.exe" /IM cmd.exe 
) 
)>_output-taskill.txt 
TYPE _output-taskill.txt 
-2

Пара линий поможет вам достичь этого:

TITLE exclude 
taskkill /IM cmd.exe /FI "WINDOWTITLE ne exclude*"