写一个C++的windows服务程序,当服务启动后,拉起一个子进程,该子进程拥有和桌面交互的能力
时间: 2024-03-21 08:38:55 浏览: 169
用C++.NET编写windows服务
5星 · 资源好评率100%
好的,以下是一个基本的C++服务程序,可以在服务启动时拉起一个子进程,并让该子进程拥有与桌面交互的能力:
```cpp
#include <windows.h>
#include <tchar.h>
#include <string>
// 子进程名称
const TCHAR* CHILD_PROCESS_NAME = _T("child_process.exe");
// 服务名称
const TCHAR* SERVICE_NAME = _T("MyService");
// 服务状态句柄
SERVICE_STATUS_HANDLE g_ServiceStatusHandle;
// 服务状态
SERVICE_STATUS g_ServiceStatus = { 0 };
// 子进程句柄
HANDLE g_hChildProcess = NULL;
// 服务退出事件句柄
HANDLE g_hServiceStopEvent = NULL;
// 服务控制处理函数
void WINAPI ServiceCtrlHandler(DWORD dwControl)
{
switch (dwControl)
{
case SERVICE_CONTROL_STOP:
// 服务停止事件已被触发,将服务状态设置为停止中
g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
// 向子进程发送停止消息
if (g_hChildProcess != NULL)
{
PostThreadMessage(GetThreadId(g_hChildProcess), WM_QUIT, 0, 0);
}
// 设置服务退出事件
SetEvent(g_hServiceStopEvent);
break;
default:
break;
}
}
// 子进程过程函数
LRESULT CALLBACK ChildProcessWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
// 在子进程中创建一个窗口
CreateWindow(_T("BUTTON"), _T("Click me!"), WS_VISIBLE | WS_CHILD, 10, 10, 100, 30, hWnd, NULL, NULL, NULL);
break;
case WM_DESTROY:
// 窗口被销毁,退出消息循环
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
// 子进程线程函数
DWORD WINAPI ChildProcessThread(LPVOID lpParam)
{
// 注册子进程窗口类
WNDCLASS wc = { 0 };
wc.lpfnWndProc = ChildProcessWndProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = _T("MyChildWindowClass");
RegisterClass(&wc);
// 创建子进程窗口
HWND hWnd = CreateWindow(_T("MyChildWindowClass"), _T("My Child Window"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 200, NULL, NULL, GetModuleHandle(NULL), NULL);
// 进入消息循环
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
// 服务主函数
void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
// 注册服务控制处理函数
g_ServiceStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler);
if (g_ServiceStatusHandle == NULL)
{
return;
}
// 设置服务状态
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
// 创建服务退出事件
g_hServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
// 启动子进程
STARTUPINFO si = { 0 };
si.cb = sizeof(si);
PROCESS_INFORMATION pi = { 0 };
if (CreateProcess(NULL, (LPWSTR)CHILD_PROCESS_NAME, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
g_hChildProcess = pi.hThread;
// 等待服务退出事件
WaitForSingleObject(g_hServiceStopEvent, INFINITE);
// 关闭子进程
TerminateThread(g_hChildProcess, 0);
CloseHandle(g_hChildProcess);
g_hChildProcess = NULL;
}
// 关闭服务退出事件
CloseHandle(g_hServiceStopEvent);
g_hServiceStopEvent = NULL;
// 设置服务状态为停止
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
}
// 入口函数
int _tmain(int argc, _TCHAR* argv[])
{
// 安装服务
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
SC_HANDLE hService = CreateService(hSCM, SERVICE_NAME, SERVICE_NAME, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, argv[0], NULL, NULL, NULL, NULL, NULL);
if (hService != NULL)
{
// 启动服务
StartService(hService, 0, NULL);
// 等待服务退出
SERVICE_STATUS status = { 0 };
while (QueryServiceStatus(hService, &status) && status.dwCurrentState != SERVICE_STOPPED)
{
Sleep(1000);
}
// 卸载服务
DeleteService(hService);
CloseServiceHandle(hService);
}
CloseServiceHandle(hSCM);
return 0;
}
```
这个服务程序会在启动时拉起一个名为`child_process.exe`的子进程,该子进程会创建一个窗口,并拥有与桌面交互的能力。具体实现中,服务程序会创建一个进程,将其运行在用户的会话中,然后将进程的窗口句柄附加到桌面上,最后在进程中创建一个窗口。需要注意的是,子进程的代码需要单独编写,这里只提供了服务程序的代码。
阅读全文