c++ Windows后台服务,定时监控进程,若未打开则重启带UI界面的进程
时间: 2023-11-25 13:08:47 浏览: 35
你可以使用 Windows API 中的服务控制管理器(SCM)来创建一个后台服务。下面是一个简单的示例代码,可以通过该代码启动一个后台服务,并使用定时器监视指定进程是否在运行:
```cpp
#include <windows.h>
#include <tchar.h>
// 定义服务名称和显示名称
#define SERVICE_NAME _T("MyService")
#define DISPLAY_NAME _T("My Service")
// 定义监视的进程名称
#define PROCESS_NAME _T("MyProcess.exe")
// 服务控制处理函数
VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv);
VOID WINAPI ServiceCtrlHandler(DWORD dwCtrl);
// 定义全局变量
SERVICE_STATUS g_ServiceStatus = {0};
SERVICE_STATUS_HANDLE g_hServiceStatus = NULL;
// 定义定时器句柄和时间间隔
HANDLE g_hTimer = NULL;
DWORD g_dwInterval = 5000; // 5秒
// 定义进程句柄
HANDLE g_hProcess = NULL;
int _tmain(int argc, TCHAR* argv[])
{
// 定义服务表
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{ SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ NULL, NULL }
};
// 注册服务控制处理函数
if (!StartServiceCtrlDispatcher(ServiceTable))
{
return GetLastError();
}
return 0;
}
VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
// 注册服务控制处理函数
g_hServiceStatus = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);
if (!g_hServiceStatus)
{
return;
}
// 设置服务状态为运行中
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
SetServiceStatus(g_hServiceStatus, &g_ServiceStatus);
// 创建定时器
g_hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
if (!g_hTimer)
{
return;
}
// 设置定时器时间间隔
LARGE_INTEGER liDueTime;
liDueTime.QuadPart = -10000LL * g_dwInterval;
SetWaitableTimer(g_hTimer, &liDueTime, g_dwInterval, NULL, NULL, FALSE);
// 进入主循环
HANDLE hEvents[2] = { g_hTimer, NULL };
DWORD dwIndex;
while (g_ServiceStatus.dwCurrentState == SERVICE_RUNNING)
{
// 等待定时器事件或停止事件
dwIndex = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
// 处理事件
if (dwIndex == WAIT_OBJECT_0) // 定时器事件
{
// 检查进程是否在运行
if (g_hProcess == NULL || WaitForSingleObject(g_hProcess, 0) != WAIT_TIMEOUT)
{
// 进程未运行,启动进程
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
if (CreateProcess(NULL, PROCESS_NAME, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
// 保存进程句柄
g_hProcess = pi.hProcess;
}
}
// 重新设置定时器
SetWaitableTimer(g_hTimer, &liDueTime, g_dwInterval, NULL, NULL, FALSE);
}
else if (dwIndex == WAIT_OBJECT_0 + 1) // 停止事件
{
break;
}
}
// 停止服务
g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus(g_hServiceStatus, &g_ServiceStatus);
// 关闭定时器
CloseHandle(g_hTimer);
// 关闭进程句柄
if (g_hProcess)
{
CloseHandle(g_hProcess);
}
// 设置服务状态为已停止
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(g_hServiceStatus, &g_ServiceStatus);
}
VOID WINAPI ServiceCtrlHandler(DWORD dwCtrl)
{
switch (dwCtrl)
{
case SERVICE_CONTROL_STOP:
// 停止服务
g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus(g_hServiceStatus, &g_ServiceStatus);
SetEvent(g_hStopEvent);
break;
default:
break;
}
}
```
在上面的代码中,我们使用 `CreateWaitableTimer` 函数创建了一个等待定时器事件的句柄 `g_hTimer`,然后使用 `SetWaitableTimer` 函数设置了定时器的时间间隔和触发方式。在主循环中,我们使用 `WaitForMultipleObjects` 函数等待定时器事件或停止事件,然后根据事件类型进行处理。在定时器事件中,我们检查指定进程是否在运行,如果未运行则启动带 UI 界面的进程。在停止事件中,我们退出主循环并停止服务。同时,我们还使用了 Windows API 中的服务控制管理器函数来注册服务控制处理函数,并在处理函数中实现了停止服务的功能。