gpt4 book ai didi

c++ - 在 Windows 服务中使用命名管道时出现问题

转载 作者:可可西里 更新时间:2023-11-01 14:22:02 26 4
gpt4 key购买 nike

我正在为 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\\0x0\\source\\Service\\output.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("\\\\.\\pipe\\ServicePipe"),
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
128,
16 * 1024,
16 * 1024,
0,
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)\\Unility\\utility.exe\" " + args;

if (!CreateProcessW(NULL, (LPWSTR)command.c_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &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, TRUE, 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, 0, ServiceWorkerThread, NULL, 0, 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, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
ZeroMemory(&pi, sizeof(pi));

HANDLE service_pipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\ServicePipe"),
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
128,
16 * 1024,
16 * 1024,
0,
nullptr);

if (service_pipe == INVALID_HANDLE_VALUE)
{
return;
}

TCHAR inbox_buffer[1024];
std::fill(inbox_buffer, inbox_buffer + 1024, '\0');
DWORD read, write;

while (true)
{

if (ConnectNamedPipe(service_pipe, nullptr))
{
if (ReadFile(service_pipe, inbox_buffer, 1024 * sizeof(TCHAR), &read, 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)\\Unility\\utility.exe\" " + args;

if (!CreateProcessW(NULL, (LPWSTR)command.c_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &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, L"executed", sizeof(L"executed"), &write, nullptr);
} while (!success);
}
DisconnectNamedPipe(service_pipe);
std::fill(inbox_buffer, inbox_buffer + 1024, '\0');
}
}
CloseHandle(service_pipe);
}

DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
if (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0) {
Sleep(1000);
}

service::handle gsprint_pipe = CreateFile(TEXT("\\\\.\\pipe\\ServicePipe"),
GENERIC_READ | GENERIC_WRITE,
0,
nullptr,
OPEN_EXISTING,
0,
nullptr);
bool succeess = false;
DWORD read;
do
{
succeess = WriteFile(gsprint_pipe, L"stop_signal", sizeof(L"stop_signal"), &read, 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, 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)
{
//SetServiceStatus failed. You should log this!
}

g_ServiceStopEvent = CreateEvent(NULL, TRUE, 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)
{
//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, 0, ServiceWorkerThread, NULL, 0, NULL);

WaitForSingleObject(hThread, 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, TCHAR *argv[])
{
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{(LPWSTR)"TestService", (LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL, NULL}
};

if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
{
return GetLastError();
}

return 0;
}

关于c++ - 在 Windows 服务中使用命名管道时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52149153/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com