web-dev-qa-db-ja.com

プロセスがバッチスクリプトを介して実行されているかどうかを確認する方法

アプリケーションがバッチ(well cmd)ファイルから実行されているかどうかを確認する方法を教えてください。

プログラムがすでに実行されている場合は、別のインスタンスを起動する必要はありません。 (私はそれが単一のインスタンスだけになるようにアプリを変更することはできません。)

また、アプリケーションは任意のユーザーとして実行されている可能性があります。

238
Matt Lacey

grep を使用したことに触発された、私が思いついたもう1つの可能性は:

tasklist /FI "IMAGENAME eq myapp.exe" 2>NUL | find /I /N "myapp.exe">NUL
if "%ERRORLEVEL%"=="0" echo Program is running

余分なファイルを保存する必要はないので、この方法をお勧めします。

298
Chaosmaster

これが私がどのように解決したかです:

tasklist /FI "IMAGENAME eq notepad.exe" /FO CSV > search.log

FOR /F %%A IN (search.log) DO IF %%~zA EQU 0 GOTO end

start notepad.exe

:end

del search.log

まだ実行されていない場合、上記は メモ帳 を開きます。

編集:これはタスクリストから隠されたアプリケーションを見つけることはありません。これらのタスクは自動的に非表示になるため、これには別のユーザーとして実行されているスケジュール済みタスクも含まれます。

59
Matt Lacey

私はChaosmasterの解決策が好きです!しかし、私は find.exefindstr.exe(のような)他の外部プログラムを起動させない解決策を探しました )。そこで私はMatt Laceyの解決策からのアイデアを追加しました。最後に、私はかなり単純な解決策を見つけることができたので、私はそれを共有します...

SETLOCAL EnableExtensions
set EXE=myprog.exe
FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF %%x == %EXE% goto FOUND
echo Not running
goto FIN
:FOUND
echo Running
:FIN

これはうまく私のために働いています...

37
TrueY

Windowsでは、Windows Management Instrumentation(WMI)を使用して、指定したコマンドラインを持つアプリが起動されないようにすることができます。次に例を示します。

wmic process where (name="nmake.exe") get commandline | findstr /i /c:"/f load.mak" /c:"/f build.mak" > NUL && (echo THE BUILD HAS BEEN STARTED ALREADY! > %ALREADY_STARTED% & exit /b 1)

21
vtrz

TASKLISTの代わりにQPROCESSを使用するというnpocmakaの提案は素晴らしいですが、その答えは非常に大きく複雑であるため、非常に単純化したバージョンを投稿することが義務付けられていると思います。

QPROCESS "myprocess.exe">NUL
IF %ERRORLEVEL% EQU 0 ECHO "Process running"

上記のコードはWindows 7でテストされており、管理者は厳格なユーザーです。

18
aldemarcalazans

TrueYの答えは最も洗練された解決策のように思えました、しかし、私は正確に何が起こっているのか理解していなかったので、私はいくらか厄介をしなければならなかった。うまくいけば、次の人のために時間を節約するために物事を整理しましょう。

TrueYの修正された答え:

::Change the name of notepad.exe to the process .exe that you're trying to track
::Process names are CASE SENSITIVE, so notepad.exe works but Notepad.exe does NOT
::Do not change IMAGENAME
::You can Copy and Paste this into an empty batch file and change the name of
::notepad.exe to the process you'd like to track
::Also, some large programs take a while to no longer show as not running, so
::give this batch a few seconds timer to avoid a false result!!

@echo off
SETLOCAL EnableExtensions

set EXE=notepad.exe

FOR /F %%x IN ('tasklist /NH /FI "IMAGENAME eq %EXE%"') DO IF %%x == %EXE% goto ProcessFound

goto ProcessNotFound

:ProcessFound

echo %EXE% is running
goto END
:ProcessNotFound
echo %EXE% is not running
goto END
:END
echo Finished!

とにかく、それが役立つことを願っています。私は時々あなたが私のような初心者のような人である場合時々バッチ/コマンドラインを読むことは一種の混乱の種になることができることを知っています。

8

私はのようなバッチファイルでProgram Files\PVにインストールされた http://www.teamcti.com/pview/prcview.htm からPV.exeを使用しますこの:

@echo off
PATH=%PATH%;%PROGRAMFILES%\PV;%PROGRAMFILES%\YourProgram
PV.EXE YourProgram.exe >nul
if ERRORLEVEL 1 goto Process_NotFound
:Process_Found
echo YourProgram is running
goto END
:Process_NotFound
echo YourProgram is not running
YourProgram.exe
goto END
:END
8
Adam

Matt Laceyによる回答 はWindows XPで動作します。しかし、Windows Server 2003では、この行は

 tasklist /FI "IMAGENAME eq notepad.exe" /FO CSV > search.log

戻る

情報:指定された基準に一致するタスクは実行されていません。

これはプロセスの実行中に読み込まれます。

私はバッチスクリプティングの経験が豊富ではないので、search.logファイルでプロセス名を検索し、その結果を別のファイルに出力して、それを任意の出力で検索するのが賢明です。

tasklist /FI "IMAGENAME eq notepad.exe" /FO CSV > search.log

FINDSTR notepad.exe search.log > found.log

FOR /F %%A IN (found.log) DO IF %%~zA EQU 0 GOTO end

start notepad.exe

:end

del search.log
del found.log

私はこれが他の人に役立つことを願っています。

6
benmod
TASKLIST | FINDSTR ProgramName || START "" "Path\ProgramName.exe"
6

WMICおよびTASKLISTツールは好きですが、home/basicエディションのWindowsでは使用できません。別の方法は、ほぼすべてのWindowsマシンで使用可能なQPROCESSコマンドを使用することです(ターミナルサービスがあるマシンの場合-勝つだけだと思いますXPSP2なしで、実際にはすべてのWindowsマシン):

@echo off
:check_process
setlocal
if "%~1" equ "" echo pass the process name as forst argument && exit /b 1
:: first argument is the process you want to check if running
set process_to_check=%~1
:: QPROCESS can display only the first 12 symbols of the running process
:: If other tool is used the line bellow could be deleted
set process_to_check=%process_to_check:~0,12%

QPROCESS * | find /i "%process_to_check%" >nul 2>&1 && (
    echo process %process_to_check%  is running
) || (
    echo process %process_to_check%  is not running
)
endlocal

QPROCESS コマンドはTASKLISTほど強力ではなく、プロセス名の12シンボルのみの表示に制限されていますが、考慮する必要がありますTASKLISTが利用できない場合。

引数としてプロセスを使用する場合、名前を使用するより簡単な使用法(この場合、実行可能ファイル名を渡す場合、.exeサフィックスは必須です):

@echo off
:check_process
setlocal
if "%~1" equ "" echo pass the process name as forst argument && exit /b 1
:: first argument is the process you want to check if running
:: .exe suffix is mandatory
set "process_to_check=%~1"


QPROCESS "%process_to_check%" >nul 2>&1 && (
    echo process %process_to_check%  is running
) || (
    echo process %process_to_check%  is not running
)
endlocal

QPROCESSを使用する2つの方法の違いは、QPROCESS *がすべてのプロセスをリストするのに対し、QPROCESS some.exeは現在のユーザーのプロセスのみをフィルタリングすることです。

また、WMIの代わりにWindowsスクリプトHost exeを介してWMICオブジェクトを使用することもオプションです。これは、すべてのWindowsマシンでも実行する必要があります(WSHがオフになっているが、これはまれなケースです)。 WMIクラスを通じて、上記のスクリプトでQPROCESSの代わりに使用できます(jscript/batハイブリッドであり、.batとして保存する必要があります)。

@if (@X)==(@Y) @end /* JSCRIPT COMMENT **


@echo off
cscript //E:JScript //nologo "%~f0"
exit /b

************** end of JSCRIPT COMMENT **/


var winmgmts = GetObject("winmgmts:\\\\.\\root\\cimv2");
var colProcess = winmgmts.ExecQuery("Select * from Win32_Process");
var processes =  new Enumerator(colProcess);
for (;!processes.atEnd();processes.moveNext()) {
    var process=processes.item();
    WScript.Echo( process.processID + "   " + process.Name );
}

そして、プロセスが実行されているかどうかを確認する変更:

@if (@X)==(@Y) @end /* JSCRIPT COMMENT **


@echo off
if "%~1" equ "" echo pass the process name as forst argument && exit /b 1
:: first argument is the process you want to check if running
set process_to_check=%~1

cscript //E:JScript //nologo "%~f0" | find /i "%process_to_check%" >nul 2>&1 && (
    echo process %process_to_check%  is running
) || (
    echo process %process_to_check%  is not running
)

exit /b

************** end of JSCRIPT COMMENT **/


var winmgmts = GetObject("winmgmts:\\\\.\\root\\cimv2");
var colProcess = winmgmts.ExecQuery("Select * from Win32_Process");
var processes =  new Enumerator(colProcess);
for (;!processes.atEnd();processes.moveNext()) {
    var process=processes.item();
    WScript.Echo( process.processID + "   " + process.Name );
}

2つのオプションは、TASKLISTを持たないマシンで使用できます。

究極のテクニックはMSHTAを使用することです。これは、XP以降のすべてのWindowsマシンで実行され、Windowsスクリプトのホスト設定に依存しません。ただし、MSHTAを呼び出すと、パフォーマンスが少し低下する可能性があります(これもバットとして保存する必要があります)。

@if (@X)==(@Y) @end /* JSCRIPT COMMENT **
@echo off

setlocal
if "%~1" equ "" echo pass the process name as forst argument && exit /b 1
:: first argument is the process you want to check if running

set process_to_check=%~1


mshta "about:<script language='javascript' src='file://%~dpnxf0'></script>" | find /i "%process_to_check%" >nul 2>&1 && (
    echo process %process_to_check%  is running
) || (
    echo process %process_to_check%  is not running
)
endlocal
exit /b
************** end of JSCRIPT COMMENT **/


   var fso= new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1);


   var winmgmts = GetObject("winmgmts:\\\\.\\root\\cimv2");
   var colProcess = winmgmts.ExecQuery("Select * from Win32_Process");
   var processes =  new Enumerator(colProcess);
   for (;!processes.atEnd();processes.moveNext()) {
    var process=processes.item();
    fso.Write( process.processID + "   " + process.Name + "\n");
   }
   close();
5
npocmaka

内蔵CMDでそのようにする方法はわかりませんが、 grep があれば、次のことを試すことができます。

tasklist /FI "IMAGENAME eq myApp.exe" | grep myApp.exe
if ERRORLEVEL 1 echo "myApp is not running"
2
Motti

ちなみに、あなたのタスク名が本当に長いのであれば、それがtasklistの結果に完全には現れないので、反対をチェックする方が安全かもしれません(ローカライズ以外)。

この答えのバリエーション:

:: in case your task name is really long, check for the 'opposite' and find  the message when it's not there
tasklist /fi "imagename eq yourreallylongtasknamethatwontfitinthelist.exe" 2>NUL | find /I /N "no tasks are running">NUL
if "%errorlevel%"=="0" (
    echo Task Found
) else (
    echo Not Found Task
)
1
drzaus

私はここで窓を想定しています。そのため、その情報を入手するにはWMIを使用する必要があります。スクリプトからWMIを使用する方法の例については、The Scripting Guyの アーカイブ をご覧ください。

0
NotMe

私は Matt (2008-10-02)が提供するスクリプトを使いました。私が悩んでいた唯一のことはそれがsearch.logファイルを削除しないということでした。私は私のプログラムを開始するために別の場所にcdを使わなければならなかったので、私は期待します。 cdでBATファイルとsearch.logがある場所に戻りますが、それでも削除できません。それで私はsearch.logファイルを最後ではなく最初に削除することによってそれを解決しました。

del search.log

tasklist /FI "IMAGENAME eq myprog.exe" /FO CSV > search.log

FOR /F %%A IN (search.log) DO IF %%-zA EQU 0 GOTO end

cd "C:\Program Files\MyLoc\bin"

myprog.exe myuser mypwd

:end
0
Nin

親プロセス名を確認してください。 .NETベースのソリューション** についての The Code Project の記事を参照してください。

プログラム的でないチェック方法

  1. Cmd.exeを起動します。
  2. アプリケーションを起動します(例:c:\windows\notepad.exe
  3. Process Explorer でNotepad.exeプロセスのプロパティを確認してください。
  4. 親プロセスをチェックします(これはcmd.exeを示しています)

親プロセス名を取得しても同じことが確認できます。

0
prakash