如何使用C++确定应用程序是否已在窗口中启动?
How to determine an application is already launched or not in windows using C++?
我正在启动一个Windows桌面应用程序 CATStartProcess (const char *comPath, char *const argv[], int wait, int *pid, int *exitStatus(; 参数将传递给它。 如果应用程序已经在运行,则无需为此创建新实例。如何检查此应用程序是否已在后台运行?
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";
相关文章:
- 如何使用C++确定应用程序是否已在窗口中启动?
- 无法启动 OpenGL 窗口
- 在SFML(C++)中启动一个新窗口
- FreeGLUT窗口在启动时消失
- 使用 c++ 在 Mac OS X 上启动"new email"窗口
- 从窗口启动程序时如何查看键盘修饰符?
- 如何在最大化窗口中启动 VTK 程序
- 在 d3d->CreateDevice 中D3DERR_INVALIDCALL,导致在 Allegro 5 D3D 程序中启动时窗口闪烁
- 系统( "bcdedit /set safeboot" ) 未将窗口设置为安全启动
- 使用启动命令启动命令时,将命令传递到另一个 cmd 窗口
- 强制将以SW_HIDE启动的进程中的窗口显示为STARTUPINFO
- 有没有办法接收有关在窗口中启动的进程的事件
- 查询/查找启动过程窗口
- 基于CDialog的应用程序启动时,如何将我的辅助对话框窗口带到顶部
- 如何在新的终端窗口中启动 ./a.out
- Qt:缓慢启动时显示窗口内容
- 从控制台应用程序启动窗口应用程序
- SDL窗口在启动时关闭并返回0
- Visual Studio:如何在没有控制台窗口的情况下启动项目
- 以弹出窗口的形式启动另一个应用程序