c++实现Windows后台服务,从配置文件读取进程名和绝对路径,判断进程是否在运行,定时监控和重启
时间: 2023-06-19 09:10:20 浏览: 192
基于C++实现的百万并发的后台服务框架源码
实现Windows后台服务可以使用Windows服务的API。以下是一个简单的实现过程:
1. 创建一个Windows服务程序,使用Visual Studio或其他编译器。
2. 在服务程序中添加代码,从配置文件中读取进程名和绝对路径。可以使用Windows API函数GetPrivateProfileString()从INI配置文件中读取。
3. 使用Windows API函数OpenProcess()和EnumProcesses()枚举所有进程,检查是否有与配置文件中的进程名匹配的进程正在运行。
4. 如果进程未运行,则使用Windows API函数CreateProcess()启动进程。
5. 使用Windows API函数SetTimer()定时监控进程是否在运行,如果进程未运行,则使用Windows API函数TerminateProcess()终止进程,并使用Windows API函数CreateProcess()重新启动进程。
6. 在Windows服务程序中实现Windows服务的功能,例如启动、停止、暂停和继续。
7. 在Windows服务程序的主函数中注册服务,使用Windows API函数RegisterServiceCtrlHandler()和SetServiceStatus()来处理服务状态。
8. 编译、安装并启动服务。
需要注意的是,在Windows服务程序中,必须使用Windows API函数RegisterServiceProcess()来注册服务进程,否则服务程序可能会被操作系统杀死。
下面是一个简单的示例代码,可以用来实现从配置文件中读取进程名和路径,并检查进程是否在运行:
```
#include <Windows.h>
#include <tchar.h>
#include <iostream>
#include <string>
#define MAX_PROCESS_NAME 1024
SERVICE_STATUS g_ServiceStatus;
SERVICE_STATUS_HANDLE g_StatusHandle;
std::string g_ProcessName;
std::string g_ProcessPath;
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv);
VOID WINAPI ServiceCtrlHandler(DWORD);
VOID ReportStatus(DWORD, DWORD, DWORD);
VOID MonitorProcess();
int _tmain(int argc, _TCHAR* argv[])
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = _T("MyService");
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
if (!StartServiceCtrlDispatcher(ServiceTable)) {
std::cout << "StartServiceCtrlDispatcher failed, error code: " << GetLastError() << std::endl;
return 1;
}
return 0;
}
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
{
g_StatusHandle = RegisterServiceCtrlHandler(_T("MyService"), ServiceCtrlHandler);
if (g_StatusHandle == NULL) {
std::cout << "RegisterServiceCtrlHandler failed, error code: " << GetLastError() << std::endl;
return;
}
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
ReportStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
// Read process name and path from configuration file
char processName[MAX_PROCESS_NAME] = { 0 };
char processPath[MAX_PATH] = { 0 };
GetPrivateProfileStringA("Process", "Name", "", processName, MAX_PROCESS_NAME, "config.ini");
GetPrivateProfileStringA("Process", "Path", "", processPath, MAX_PATH, "config.ini");
g_ProcessName = processName;
g_ProcessPath = processPath;
ReportStatus(SERVICE_RUNNING, NO_ERROR, 0);
MonitorProcess();
}
VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode)
{
switch (CtrlCode) {
case SERVICE_CONTROL_PAUSE:
ReportStatus(SERVICE_PAUSE_PENDING, NO_ERROR, 0);
// TODO: Implement pause operation
ReportStatus(SERVICE_PAUSED, NO_ERROR, 0);
break;
case SERVICE_CONTROL_CONTINUE:
ReportStatus(SERVICE_CONTINUE_PENDING, NO_ERROR, 0);
// TODO: Implement continue operation
ReportStatus(SERVICE_RUNNING, NO_ERROR, 0);
break;
case SERVICE_CONTROL_STOP:
ReportStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
// TODO: Implement stop operation
ReportStatus(SERVICE_STOPPED, NO_ERROR, 0);
break;
case SERVICE_CONTROL_INTERROGATE:
ReportStatus(g_ServiceStatus.dwCurrentState, NO_ERROR, 0);
break;
default:
break;
}
}
VOID ReportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
g_ServiceStatus.dwCurrentState = dwCurrentState;
g_ServiceStatus.dwWin32ExitCode = dwWin32ExitCode;
g_ServiceStatus.dwWaitHint = dwWaitHint;
if (dwCurrentState == SERVICE_START_PENDING) {
g_ServiceStatus.dwControlsAccepted = 0;
}
else {
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
}
if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED)) {
g_ServiceStatus.dwCheckPoint = 0;
}
else {
g_ServiceStatus.dwCheckPoint = dwCheckPoint++;
}
SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
}
VOID MonitorProcess()
{
HANDLE hProcess = NULL;
while (g_ServiceStatus.dwCurrentState == SERVICE_RUNNING) {
// Check if process is running
DWORD aProcesses[1024], cbNeeded, cProcesses;
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) {
std::cout << "EnumProcesses failed, error code: " << GetLastError() << std::endl;
break;
}
cProcesses = cbNeeded / sizeof(DWORD);
for (DWORD i = 0; i < cProcesses; i++) {
if (aProcesses[i] != 0) {
TCHAR szProcessName[MAX_PROCESS_NAME] = TEXT("<unknown>");
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]);
if (hProcess != NULL) {
HMODULE hMod;
DWORD cbNeeded;
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {
GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR));
std::string processName(szProcessName);
if (processName == g_ProcessName) {
// Process is running
CloseHandle(hProcess);
hProcess = NULL;
break;
}
}
CloseHandle(hProcess);
hProcess = NULL;
}
}
}
if (hProcess == NULL) {
// Process is not running, start it
STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcessA(NULL, (LPSTR)g_ProcessPath.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
std::cout << "CreateProcess failed, error code: " << GetLastError() << std::endl;
break;
}
}
Sleep(1000);
}
if (hProcess != NULL) {
TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
}
}
```
阅读全文