繁体   English   中英

如何使用 C++ 在 Windows 中确定应用程序是否已启动?

[英]How to determine an application is already launched or not in windows using C++?

我正在通过 CATStartProcess (const char *comPath, char *const argv[], int wait, int *pid, int *exitStatus) 启动 Windows 桌面应用程序; 参数传递给它。 如果应用程序已经在运行,我不需要为此创建一个新实例。 如何检查此应用程序是否已在后台运行?

    int wait = 0;   
    int pid;
    int exitStatus;
    char *CommandArgs[9] = { 0 };
    CommandArgs[0] = (char*)usComposerExePath.ConvertToChar();
    CommandArgs[1] = (char*)usOpen.ConvertToChar();
    CommandArgs[2] = (char*)usComposerProjectDocPath.ConvertToChar();
    CommandArgs[3] = (char*)strInfiniteTicket.ConvertToChar();
    CommandArgs[4] = (char*)strDocName.ConvertToChar();
    CommandArgs[5] = (char*)strSecurityContext.ConvertToChar();     
    CommandArgs[6] = (char*)usBusID.ConvertToChar();
    CommandArgs[7] = (char*)usUserID.ConvertToChar();
    CommandArgs[8] = NULL;

    CATLibStatus startComposerBatchStatus = CATStartProcess((char*)usComposerExePath.ConvertToChar(), CommandArgs, wait, &pid, &exitStatus);

有几种方法,但我承认,我的两个解决方案都不是可移植/标准 C++,但是您标记了 Windows,所以我将给出一个 Windows 方法。

下面的代码实际上执行了这两项检查。 第一种方法是使用命名的互斥锁。 Windows 有一个“全局”互斥锁,它检查任何用户正在运行的进程。 如果互斥锁已经存在,则它正在运行。 如果它不存在,则它不会运行。 有些状态无法轻易确定,因此它会检查正在运行的进程列表。 这部分不太准确,因为不同的权限会影响列表。

只有当您可以修改尝试启动的应用程序以创建互斥锁时,带有互斥锁的部分才会起作用。

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#include <psapi.h>
#include <TlHelp32.h>
#include <shellapi.h>
#include <advpub.h>

enum class ProcessRunningState {
    YES,
    NO,
    ERR
};

ProcessRunningState CheckIfProcessIsAlreadyRunning( DWORD currentProcessId, const wchar_t *programName, const wchar_t *programGUID, HANDLE *mutex_handle ) noexcept {

    { // Check the mutexes first
        wchar_t global_prog_name[1024] = L"Global\\";
        wcsncat_s( global_prog_name, programName, wcslen( programGUID ) );


        if ( mutex_handle ) {
            *mutex_handle = CreateMutex( NULL, TRUE, global_prog_name );
            if ( !( *mutex_handle ) ) {
                const DWORD dw = GetLastError();
                if ( dw == ERROR_ALREADY_EXISTS )
                    return ProcessRunningState::YES;
            } else {
                return ProcessRunningState::NO;
            }
        } else {
            HANDLE h = OpenMutex( SYNCHRONIZE, FALSE, global_prog_name );
            if ( h ) {
                CloseHandle( h );
                return ProcessRunningState::YES;
            } else if ( GetLastError() == ERROR_FILE_NOT_FOUND ) {
                return ProcessRunningState::NO;
            }
        }
    }

    { // At this point, the state is unknown, so try running through the process list
        DWORD aProcesses[2048], cProcesses;

        if ( !EnumProcesses( aProcesses, sizeof( aProcesses ), &cProcesses ) ) {
            return ProcessRunningState::ERR;
        }

        // Calculate how many process identifiers were returned.

        cProcesses = cProcesses / sizeof( DWORD );

        for ( unsigned int i = 0; i < cProcesses; i++ ) {
            if ( aProcesses[i] != 0 && aProcesses[i] != currentProcessId ) {
                HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] );

                WCHAR szProcessName[MAX_PATH] = { 0 };

                if ( hProcess ) {
                    HMODULE hMod;
                    DWORD cbNeeded;

                    if ( EnumProcessModules( hProcess, &hMod, sizeof( hMod ), &cbNeeded ) ) {
                        GetModuleBaseName( hProcess, hMod, szProcessName, sizeof( szProcessName ) / sizeof( TCHAR ) ); // Can't error here, since this function "errors" on access
                    }/* else {
                        return ProcessRunningState::ERR;
                    }*/

                    CloseHandle( hProcess );
                }

                if ( _wcsicmp( szProcessName, programName ) == 0 ) {
                    return ProcessRunningState::YES;
                }
            }
        }
    }

    return ProcessRunningState::NO;
}

如果可能的话,像这样调用它会创建互斥锁,并且基本上是说“我想运行,可以吗?”

HANDLE mutex_handle;
const ProcessRunningState cur_state = CheckIfProcessIsAlreadyRunning( GetCurrentProcessId(), L"PROGRAM_NAME", programGUID, &mutex_handle );

switch ( cur_state ) {
case ProcessRunningState::ERR:
case ProcessRunningState::YES:
    return ERROR_ALREADY_EXISTS;
default:
    break;
}

像这样调用它,只需检查它是否已经运行,如果没有,则启动应用程序。

if ( CheckIfProcessIsAlreadyRunning( GetCurrentProcessId(), L"PROGRAM_NAME", programGUID, nullptr ) == ProcessRunningState::NO ) {
    std::wstring programInstallLocation = L"path";
    std::wstring programName = programInstallLocation + L"\\PROGRAM_NAME";
    ShellExecute( NULL, L"open", programName.c_str(), NULL, NULL, SW_SHOW );
}

在您的代码中的某处,您将指定programGUID是什么。 例如:

WCHAR programGUID[] = L"ba2e95a0-9168-4b6e-bcd6-57309748df21";

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM