写一个C++的windows服务程序,当服务启动后,拉起一个子进程,该子进程拥有和桌面交互的能力
时间: 2024-03-21 11:38:57 浏览: 18
好的,以下是一个简单的C++的Windows服务程序,启动后会拉起一个子进程,并且该子进程拥有和桌面交互的能力。
```cpp
#include <Windows.h>
SERVICE_STATUS g_ServiceStatus = { 0 };
SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE;
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv);
VOID WINAPI ServiceCtrlHandler(DWORD);
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
int _tmain(int argc, TCHAR* argv[])
{
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{ TEXT("MyService"), (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ NULL, NULL }
};
if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
{
return GetLastError();
}
return 0;
}
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
{
DWORD Status = E_FAIL;
g_StatusHandle = RegisterServiceCtrlHandler(TEXT("MyService"), ServiceCtrlHandler);
if (g_StatusHandle == NULL)
{
goto EXIT;
}
g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (g_ServiceStopEvent == NULL)
{
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
goto EXIT;
}
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
EXIT:
if (g_ServiceStopEvent != NULL)
{
CloseHandle(g_ServiceStopEvent);
}
return;
}
VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode)
{
switch (CtrlCode)
{
case SERVICE_CONTROL_STOP:
if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
{
break;
}
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
g_ServiceStatus.dwWaitHint = 2000;
SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
SetEvent(g_ServiceStopEvent);
break;
}
}
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
si.cb = sizeof(si);
si.lpDesktop = _T("WinSta0\\Default");
if (!CreateProcess(NULL, _T("C:\\Windows\\System32\\notepad.exe"), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
return GetLastError();
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return ERROR_SUCCESS;
}
```
该服务程序启动后,会拉起 `notepad` 进程并且该进程拥有和桌面交互的能力。需要注意的是,在 `STARTUPINFO` 结构体中设置了 `lpDesktop` 属性,将其设置为 `"WinSta0\\Default"`,这样可以确保子进程能够拥有和桌面交互的能力。