c – 在Windows服务中使用命名管道时出现故障
发布时间:2020-12-16 07:23:52 所属栏目:百科 来源:网络整理
导读:我正在为 Windows 10创建服务.我已经按照本教程. https://www.codeproject.com/Articles/499465/Simple-Windows-Service-in-Cplusplus 但是,当我将代码添加到此示例时,发生了一些事情,我无法停止服务列表中的服务.我只能从任务经理那里阻止它.但如果我评论我
我正在为
Windows 10创建服务.我已经按照本教程.
https://www.codeproject.com/Articles/499465/Simple-Windows-Service-in-Cplusplus
但是,当我将代码添加到此示例时,发生了一些事情,我无法停止服务列表中的服务.我只能从任务经理那里阻止它.但如果我评论我的代码,服务正常停止. 我会很感激任何建议.代码如下. #include <Windows.h> #include <tchar.h> #include <string> #include <fstream> SERVICE_STATUS g_ServiceStatus = { 0 }; SERVICE_STATUS_HANDLE g_StatusHandle = NULL; HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE; std::wofstream output(L"C:Users x0sourceServiceoutput.txt"); VOID WINAPI ServiceMain(DWORD argc,LPTSTR *argv); VOID WINAPI ServiceCtrlHandler(DWORD); DWORD WINAPI ServiceWorkerThread(LPVOID lpParam); #define SERVICE_NAME _T("TestService") DWORD WINAPI ServiceWorkerThread(LPVOID lpParam) { SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; auto dwFlags = FILE_ATTRIBUTE_NORMAL; STARTUPINFOW si; GetStartupInfoW(&si); PROCESS_INFORMATION pi; ZeroMemory(&si,sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; ZeroMemory(&pi,sizeof(pi)); HANDLE service_pipe = CreateNamedPipe(TEXT("\.pipeServicePipe"),PIPE_ACCESS_DUPLEX,PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,128,16 * 1024,nullptr); if (service_pipe == INVALID_HANDLE_VALUE) { return 1; } TCHAR inbox_buffer[1024]; DWORD read,write; while (1) { if (WaitForSingleObject(g_ServiceStopEvent,0) != WAIT_OBJECT_0) { //If I comment this 'if block',service stopping properly. But I don't see any errors in this part of code. if (ConnectNamedPipe(service_pipe,nullptr)) { if (ReadFile(service_pipe,inbox_buffer,1024 * sizeof(TCHAR),&read,nullptr)) { std::wstring args = inbox_buffer; std::wstring command = L""C:Program Files (x86)Unilityutility.exe" " + args; if (!CreateProcessW(NULL,(LPWSTR)command.c_str(),NULL,TRUE,CREATE_NO_WINDOW,&si,&pi)) { output << "CreateProcessW Error = " << GetLastError() << std::endl; } WaitForSingleObject(pi.hProcess,INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); bool success = false; do { success = WriteFile(service_pipe,L"executed",sizeof(L"executed"),&write,nullptr); } while (!success); } DisconnectNamedPipe(service_pipe); } } else { output << "WaitForSingleObject(g_ServiceStopEvent,0)" << std::endl; break; } } output << "CloseHandle(service_pipe)_1" << std::endl; CloseHandle(service_pipe); output << "CloseHandle(service_pipe)_2" << std::endl; return ERROR_SUCCESS; } 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.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 4; if (SetServiceStatus(g_StatusHandle,&g_ServiceStatus) == FALSE) { output << "TestService: ServiceCtrlHandler: SetServiceStatus returned error" << std::endl; } SetEvent(g_ServiceStopEvent); output << "SetEvent(g_ServiceStopEvent)_1" << std::endl; break; default: break; } output << "SetEvent(g_ServiceStopEvent)_2" << std::endl; } VOID WINAPI ServiceMain(DWORD argc,LPTSTR *argv) { DWORD Status = E_FAIL; g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME,ServiceCtrlHandler); if (g_StatusHandle == NULL) { return; } ZeroMemory(&g_ServiceStatus,sizeof(g_ServiceStatus)); g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwServiceSpecificExitCode = 0; g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus(g_StatusHandle,&g_ServiceStatus) == FALSE) { output << "TestService: ServiceMain: SetServiceStatus returned error" << std::endl; } g_ServiceStopEvent = CreateEvent(NULL,FALSE,NULL); if (g_ServiceStopEvent == NULL) { g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = GetLastError(); g_ServiceStatus.dwCheckPoint = 1; if (SetServiceStatus(g_StatusHandle,&g_ServiceStatus) == FALSE) { output << "TestService: ServiceMain: SetServiceStatus returned error" << std::endl; } return; } g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus(g_StatusHandle,&g_ServiceStatus) == FALSE) { output << "TestService: ServiceMain: SetServiceStatus returned error" << std::endl; } HANDLE hThread = CreateThread(NULL,ServiceWorkerThread,NULL); WaitForSingleObject(hThread,INFINITE); output << "CloseHandle(g_ServiceStopEvent)_1" << std::endl; CloseHandle(g_ServiceStopEvent); output << "CloseHandle(g_ServiceStopEvent)_2" << std::endl; g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 3; if (SetServiceStatus(g_StatusHandle,&g_ServiceStatus) == FALSE) { output << "TestService: ServiceMain: SetServiceStatus returned error" << std::endl; } return; } int _tmain(int argc,TCHAR *argv[]) { SERVICE_TABLE_ENTRY ServiceTable[] = { {(LPWSTR)"TestService",(LPSERVICE_MAIN_FUNCTION)ServiceMain},{NULL,NULL} }; if (StartServiceCtrlDispatcher(ServiceTable) == FALSE) { return GetLastError(); } return 0; } 解决方法
肮脏的方式,但它的工作.我创建了一个处理与管道相关的所有工作的函数.我在新线程中运行了这个函数.当服务收到停止信号时,我向管道发送停止消息并停止循环.
#include <Windows.h> #include <tchar.h> #include <string> #include <thread> #include <fstream> 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); #define SERVICE_NAME _T("TestService") void pipe_server_function() { SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; auto dwFlags = FILE_ATTRIBUTE_NORMAL; STARTUPINFOW si; GetStartupInfoW(&si); PROCESS_INFORMATION pi; ZeroMemory(&si,nullptr); if (service_pipe == INVALID_HANDLE_VALUE) { return; } TCHAR inbox_buffer[1024]; std::fill(inbox_buffer,inbox_buffer + 1024,' '); DWORD read,write; while (true) { if (ConnectNamedPipe(service_pipe,nullptr)) { if (ReadFile(service_pipe,nullptr)) { std::wstring args = inbox_buffer; if (args.find("stop_signal") != std::wstring::npos) { DisconnectNamedPipe(service_pipe); break; } std::wstring command = L""C:Program Files (x86)Unilityutility.exe" " + args; if (!CreateProcessW(NULL,&pi)) { //CreateProcessW failed. You should log this! } WaitForSingleObject(pi.hProcess,INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); bool success = false; do { success = WriteFile(service_pipe,nullptr); } while (!success); } DisconnectNamedPipe(service_pipe); std::fill(inbox_buffer,' '); } } CloseHandle(service_pipe); } DWORD WINAPI ServiceWorkerThread(LPVOID lpParam) { if (WaitForSingleObject(g_ServiceStopEvent,0) != WAIT_OBJECT_0) { Sleep(1000); } service::handle gsprint_pipe = CreateFile(TEXT("\.pipeServicePipe"),GENERIC_READ | GENERIC_WRITE,nullptr,OPEN_EXISTING,nullptr); bool succeess = false; DWORD read; do { succeess = WriteFile(gsprint_pipe,L"stop_signal",sizeof(L"stop_signal"),nullptr); } while (!succeess); return ERROR_SUCCESS; } 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.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 4; if (SetServiceStatus(g_StatusHandle,&g_ServiceStatus) == FALSE) { //SetServiceStatus failed. You should log this! } SetEvent(g_ServiceStopEvent); break; default: break; } } VOID WINAPI ServiceMain(DWORD argc,&g_ServiceStatus) == FALSE) { //SetServiceStatus failed. You should log this! } g_ServiceStopEvent = CreateEvent(NULL,&g_ServiceStatus) == FALSE) { //SetServiceStatus failed. You should log this! } return; } g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus(g_StatusHandle,&g_ServiceStatus) == FALSE) { //SetServiceStatus failed. You should log this! } std::thread pipe_server(pipe_server_function); HANDLE hThread = CreateThread(NULL,INFINITE); pipe_server.join(); CloseHandle(g_ServiceStopEvent); g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 3; if (SetServiceStatus(g_StatusHandle,&g_ServiceStatus) == FALSE) { //SetServiceStatus failed. You should log this! } return; } int _tmain(int argc,NULL} }; if (StartServiceCtrlDispatcher(ServiceTable) == FALSE) { return GetLastError(); } return 0; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |