web-dev-qa-db-ja.com

C ++、Windowsプロセスが実行されているかどうかを確認する方法

これは、Windows XPプロセスに関するものです。

実行中のプロセスがあります。Process1と呼びましょう。 Process1は、新しいプロセスProcess2を作成し、そのIDを保存します。

さて、ある時点でProcess1はProcess2に何かをしたいので、まずProcess2がまだ生きており、ユーザーがそれを殺していないことを確認する必要があります。

このプロセスがまだ実行されていることを確認するにはどうすればよいですか?私はそれを作成したので、プロセスIDを持っています、IsProcessIDValid(id)の行に沿っていくつかのライブラリ関数があると思いますが、MSDNでそれを見つけることができません

56
Pedro

GetExitCodeProcess を使用できます。プロセスがまだ実行中の場合(またはその終了コード:()で終了した場合)STILL_ACTIVE259)を返します。

67
Dolphin

プロセスハンドルは、終了すると通知されます。

したがって、次のように動作します(簡潔にするためにエラー処理は削除されました)。

BOOL IsProcessRunning(DWORD pid)
{
    HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, pid);
    DWORD ret = WaitForSingleObject(process, 0);
    CloseHandle(process);
    return ret == WAIT_TIMEOUT;
}

プロセスIDはリサイクルできることに注意してください-CreateProcess呼び出しから返されるハンドルをキャッシュすることをお勧めします。

スレッドプールAPI(Vista +ではSetThreadpoolWait、古いプラットフォームではRegisterWaitForSingleObject)を使用して、プロセスの終了時にコールバックを受け取ることもできます。

編集:私は元の質問の「プロセスに何かをしたい」部分を見逃しました。何らかの小さなウィンドウで潜在的に古いデータを使用しても問題ない場合、または操作を試行せずに操作を失敗させたい場合、この手法を使用できます。プロセスが終了したためにアクションが失敗するケースを処理する必要があります。

34
Michael
#include <cstdio>
#include <windows.h>
#include <tlhelp32.h>

/*!
\brief Check if a process is running
\param [in] processName Name of process to check if is running
\returns \c True if the process is running, or \c False if the process is not running
*/
bool IsProcessRunning(const wchar_t *processName)
{
    bool exists = false;
    PROCESSENTRY32 entry;
    entry.dwSize = sizeof(PROCESSENTRY32);

    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

    if (Process32First(snapshot, &entry))
        while (Process32Next(snapshot, &entry))
            if (!wcsicmp(entry.szExeFile, processName))
                exists = true;

    CloseHandle(snapshot);
    return exists;
}
20
user152949

子プロセスを監視する別の方法は、次のことを行うワーカースレッドを作成することです。

  1. createProcess()を呼び出します
  2. call WaitForSingleObject()//ワーカースレッドは、子プロセスの実行が完了するまで待機します。 (main()関数から)戻りコードを取得することもできます。
6
Maciek

私はこれを今日見つけました、それは2003年からです。名前でプロセスを見つけます、あなたはpidさえ必要としません。

\#include windows.h

\#include tlhelp32.h

\#include iostream.h

int FIND_PROC_BY_NAME(const char *);

int main(int argc, char *argv[])

{

//  Check whether a process is currently running, or not

char szName[100]="notepad.exe";   // Name of process to find

int isRunning;

    isRunning=FIND_PROC_BY_NAME(szName);

    // Note: isRunning=0 means process not found, =1 means yes, it is found in memor
    return isRunning;
}

int FIND_PROC_BY_NAME(const char *szToFind)

// Created: 12/29/2000  (RK)

// Last modified: 6/16/2003  (RK)

// Please report any problems or bugs to [email protected]

// The latest version of this routine can be found at:

//     http://www.neurophys.wisc.edu/ravi/software/killproc/

// Check whether the process "szToFind" is currently running in memory

// This works for Win/95/98/ME and also Win/NT/2000/XP

// The process name is case-insensitive, i.e. "notepad.exe" and "NOTEPAD.EXE"

// will both work (for szToFind)

// Return codes are as follows:

//   0   = Process was not found

//   1   = Process was found

//   605 = Unable to search for process

//   606 = Unable to identify system type

//   607 = Unsupported OS

//   632 = Process name is invalid

// Change history:

//  3/10/2002   - Fixed memory leak in some cases (hSnapShot and

//                and hSnapShotm were not being closed sometimes)

//  6/13/2003   - Removed iFound (was not being used, as pointed out

//                by John Emmas)

{

    BOOL bResult,bResultm;
    DWORD aiPID[1000],iCb=1000,iNumProc,iV2000=0;
    DWORD iCbneeded,i;
    char szName[MAX_PATH],szToFindUpper[MAX_PATH];
    HANDLE hProc,hSnapShot,hSnapShotm;
    OSVERSIONINFO osvi;
    HINSTANCE hInstLib;
    int iLen,iLenP,indx;
    HMODULE hMod;
    PROCESSENTRY32 procentry;      
    MODULEENTRY32 modentry;

    // PSAPI Function Pointers.
     BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * );
     BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *,
        DWORD, LPDWORD );
     DWORD (WINAPI *lpfGetModuleBaseName)( HANDLE, HMODULE,
        LPTSTR, DWORD );

      // ToolHelp Function Pointers.
      HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ;
      BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ;
      BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ;
      BOOL (WINAPI *lpfModule32First)(HANDLE,LPMODULEENTRY32) ;
      BOOL (WINAPI *lpfModule32Next)(HANDLE,LPMODULEENTRY32) ;

    // Transfer Process name into "szToFindUpper" and
    // convert it to upper case
    iLenP=strlen(szToFind);
    if(iLenP<1 || iLenP>MAX_PATH) return 632;
    for(indx=0;indx<iLenP;indx++)
        szToFindUpper[indx]=toupper(szToFind[indx]);
    szToFindUpper[iLenP]=0;

    // First check what version of Windows we're in
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    bResult=GetVersionEx(&osvi);
    if(!bResult)     // Unable to identify system version
        return 606;

    // At Present we only support Win/NT/2000 or Win/9x/ME
    if((osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) &&
        (osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS))
        return 607;

    if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT)
    {
        // Win/NT or 2000 or XP

         // Load library and get the procedures explicitly. We do
         // this so that we don't have to worry about modules using
         // this code failing to load under Windows 95, because
         // it can't resolve references to the PSAPI.DLL.
         hInstLib = LoadLibraryA("PSAPI.DLL");
         if(hInstLib == NULL)
            return 605;

         // Get procedure addresses.
         lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))
            GetProcAddress( hInstLib, "EnumProcesses" ) ;
         lpfEnumProcessModules = (BOOL(WINAPI *)(HANDLE, HMODULE *,
            DWORD, LPDWORD)) GetProcAddress( hInstLib,
            "EnumProcessModules" ) ;
         lpfGetModuleBaseName =(DWORD (WINAPI *)(HANDLE, HMODULE,
            LPTSTR, DWORD )) GetProcAddress( hInstLib,
            "GetModuleBaseNameA" ) ;

         if( lpfEnumProcesses == NULL ||
            lpfEnumProcessModules == NULL ||
            lpfGetModuleBaseName == NULL)
            {
               FreeLibrary(hInstLib);
               return 605;
            }

        bResult=lpfEnumProcesses(aiPID,iCb,&iCbneeded);
        if(!bResult)
        {
            // Unable to get process list, EnumProcesses failed
            FreeLibrary(hInstLib);
            return 605;
        }

        // How many processes are there?
        iNumProc=iCbneeded/sizeof(DWORD);

        // Get and match the name of each process
        for(i=0;i<iNumProc;i++)
        {
            // Get the (module) name for this process

            strcpy(szName,"Unknown");
            // First, get a handle to the process
            hProc=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,
                aiPID[i]);
            // Now, get the process name
            if(hProc)
            {
               if(lpfEnumProcessModules(hProc,&hMod,sizeof(hMod),&iCbneeded) )
               {
                  iLen=lpfGetModuleBaseName(hProc,hMod,szName,MAX_PATH);
               }
            }
            CloseHandle(hProc);
            // Match regardless of lower or upper case
            if(strcmp(_strupr(szName),szToFindUpper)==0)
            {
                // Process found
                FreeLibrary(hInstLib);
                return 1;
            }
        }
    }

    if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
    {
        // Win/95 or 98 or ME

        hInstLib = LoadLibraryA("Kernel32.DLL");
        if( hInstLib == NULL )
            return FALSE ;

        // Get procedure addresses.
        // We are linking to these functions of Kernel32
        // explicitly, because otherwise a module using
        // this code would fail to load under Windows NT,
        // which does not have the Toolhelp32
        // functions in the Kernel 32.
        lpfCreateToolhelp32Snapshot=
            (HANDLE(WINAPI *)(DWORD,DWORD))
            GetProcAddress( hInstLib,
            "CreateToolhelp32Snapshot" ) ;
        lpfProcess32First=
            (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
            GetProcAddress( hInstLib, "Process32First" ) ;
        lpfProcess32Next=
            (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
            GetProcAddress( hInstLib, "Process32Next" ) ;
        lpfModule32First=
            (BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
            GetProcAddress( hInstLib, "Module32First" ) ;
        lpfModule32Next=
            (BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
            GetProcAddress( hInstLib, "Module32Next" ) ;
        if( lpfProcess32Next == NULL ||
            lpfProcess32First == NULL ||
            lpfModule32Next == NULL ||
            lpfModule32First == NULL ||
            lpfCreateToolhelp32Snapshot == NULL )
        {
            FreeLibrary(hInstLib);
            return 605;
        }

        // The Process32.. and Module32.. routines return names in all uppercase

        // Get a handle to a Toolhelp snapshot of all the systems processes.

        hSnapShot = lpfCreateToolhelp32Snapshot(
            TH32CS_SNAPPROCESS, 0 ) ;
        if( hSnapShot == INVALID_HANDLE_VALUE )
        {
            FreeLibrary(hInstLib);
            return 605;
        }

        // Get the first process' information.
        procentry.dwSize = sizeof(PROCESSENTRY32);
        bResult=lpfProcess32First(hSnapShot,&procentry);

        // While there are processes, keep looping and checking.
        while(bResult)
        {
            // Get a handle to a Toolhelp snapshot of this process.
            hSnapShotm = lpfCreateToolhelp32Snapshot(
                TH32CS_SNAPMODULE, procentry.th32ProcessID) ;
            if( hSnapShotm == INVALID_HANDLE_VALUE )
            {
                CloseHandle(hSnapShot);
                FreeLibrary(hInstLib);
                return 605;
            }
            // Get the module list for this process
            modentry.dwSize=sizeof(MODULEENTRY32);
            bResultm=lpfModule32First(hSnapShotm,&modentry);

            // While there are modules, keep looping and checking
            while(bResultm)
            {
                if(strcmp(modentry.szModule,szToFindUpper)==0)
                {
                    // Process found
                    CloseHandle(hSnapShotm);
                    CloseHandle(hSnapShot);
                    FreeLibrary(hInstLib);
                    return 1;
                }
                else
                {  // Look for next modules for this process
                    modentry.dwSize=sizeof(MODULEENTRY32);
                    bResultm=lpfModule32Next(hSnapShotm,&modentry);
                }
            }

            //Keep looking
            CloseHandle(hSnapShotm);
            procentry.dwSize = sizeof(PROCESSENTRY32);
            bResult = lpfProcess32Next(hSnapShot,&procentry);
        }
        CloseHandle(hSnapShot);
    }
    FreeLibrary(hInstLib);
    return 0;

}
5
Motes

プロセスが実行されているかどうかを確認したり確認したりすることはできません。最近の過去のある時点でプロセスwasが実行されているかどうかを確認することしかできません。プロセスは、アプリケーションによって制御されないエンティティであり、いつでも終了できます。プロセスが実行中かどうかを確認するチェックと対応するアクションの間にプロセスが終了しないことを保証する方法はありません。

最善のアプローチは、必要なアクションを実行し、プロセスが実行されていない場合にスローされる例外をキャッチすることです。

3
JaredPar

監視ツールを書いている間、私は少し異なるアプローチを取りました。

WaitForSingleObjectまたはRegisterWaitForSingleObject(これを行う)を使用するためだけに余分なスレッドをスピンアップするのは少しもったいないと感じました。私の場合、プロセスが閉じた正確な瞬間を知る必要はないので、プロセスが実際に閉じたというだけです。

代わりにGetProcessTimes()を使用しています。

https://msdn.Microsoft.com/en-us/library/windows/desktop/ms683223(v = vs.85).aspx

GetProcessTimes()は、プロセスが実際に終了した場合にのみ、プロセスのExitTimeのFILETIME構造体を返します。したがって、ExitTime構造体に値が設定されているかどうか、および時間が0でないかどうかを確認するだけです。

このソリューションは、プロセスが強制終了されたが、PIDが別のプロセスによって再利用された場合を考慮すべきです。 GetProcessTimesには、PIDではなくプロセスへのハンドルが必要です。そのため、OSは、ハンドルが特定の時点で実行されていたプロセスに対するものであることを認識しますが、それ以上ではなく、終了時間を提供します。

ExitCodeに依存すると、汚い感じがしました:/

1
Andrew

@ user152949によって提供される解決策 は、解説に記載されているように、最初のプロセスをスキップし、「exists」がtrueに設定されている場合に中断しません。修正版を提供させてください:

#include <windows.h>
#include <tlhelp32.h>

bool IsProcessRunning(const wchar_t* const processName) {
    PROCESSENTRY32 entry;
    entry.dwSize = sizeof(PROCESSENTRY32);

    const auto snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

    if (!Process32First(snapshot, &entry)) {
        CloseHandle(snapshot);
        return false;
    }

    do {
        if (!_wcsicmp(entry.szExeFile, processName)) {
            CloseHandle(snapshot);
            return true;
        }
    } while (Process32Next(snapshot, &entry));

    CloseHandle(snapshot);
    return false;
}
1
PolarBear

EnumProcesses()を呼び出して、PIDがリストにあるかどうかを確認します。

http://msdn.Microsoft.com/en-us/library/ms682629%28VS.85%29.aspx

1
Lance Rushing

JaredParは、プロセスが実行中かどうかわからないという点で正しいです。チェックした時点でプロセスが実行されていたかどうかのみを知ることができます。それはその間に死んだかもしれない。

また、PIDは非常に迅速にリサイクルできることに注意する必要があります。したがって、PIDを使用したプロセスがあるからといって、それがプロセスであることを意味するわけではありません。

プロセスでGUIDを共有します。 (プロセス1は、GUIDを生成し、コマンドラインでプロセス2に渡すことができます。)プロセス2は、そのGUIDで名前付きミューテックスを作成する必要があります。プロセス1は、タイムアウトが0のmutexのWaitForSingleObjectプロセス2がなくなった場合、戻りコードはmutexが破棄されたことを通知し、そうでない場合はタイムアウトになります。

1
Adrian McCarthy

これは私が過去に使用したソリューションです。この例はVB.netにありますが、この手法はcおよびc ++で使用しました。プロセスIDとプロセスハンドル、およびリターンコードに関するすべての問題を回避します。 Windowsは、Process2の終了方法に関係なく、mutexのリリースに非常に忠実です。私はそれが誰かに役立つことを願っています...

**PROCESS1 :-**

    Randomize()
    mutexname = "myprocess" & Mid(Format(CDbl(Long.MaxValue) * Rnd(), "00000000000000000000"), 1, 16)
    hnd = CreateMutex(0, False, mutexname)

    ' pass this name to Process2
    File.WriteAllText("mutexname.txt", mutexname)

    <start Process2>
    <wait for Process2 to start>

    pr = WaitForSingleObject(hnd, 0)
    ReleaseMutex(hnd)

    If pr = WAIT_OBJECT_0 Then

         <Process2 not running>

    Else

         <Process2 is running>

    End If
    ...

    CloseHandle(hnd)
    EXIT

    **PROCESS2 :-**

    mutexname = File.ReadAllText("mutexname.txt")
    hnd = OpenMutex(MUTEX_ALL_ACCESS Or SYNCHRONIZE, True, mutexname)
    ...

    ReleaseMutex(hnd)
    CloseHandle(hnd)
    EXIT
0
42LeapsOfFaith

CreateToolhelp32Snapshot で実行中のプロセスのスナップショットを取得し、その上でProcess32FirstおよびProcess32Next呼び出しを使用することで、実行中のプロセスを反復処理することで、プロセス(名前またはPIDが与えられている)が実行中かどうかを確認できますスナップショット。

次に、PIDまたは実行可能名のどちらで検索するかによって、結果のPROCESSENTRY32構造体のth32ProcessIDフィールドまたはszExeFileフィールドを使用できます。簡単な実装があります here

0
user2001885