我想用Microsoft Visual Studio 2015
编译的C / C ++代码创建服务。我编译了我的代码,并从app可执行文件中创建了一个sc.exe
的服务。我的代码包含一个无限循环,它在一段时间内将一个简单的字符串写入一个静态文件。创建服务并重新启动后,似乎服务自动停止。直接运行时,可执行文件正常工作。
以下是代码:
#include "stdafx.h"
#include <string>
#include <cstdio>
#include <windows.h>
using namespace std;
void write_txt_file(string file_name, string input) {
/*
write a string to a specific txt file
*/
FILE *f = fopen(file_name.c_str(), "a+");
fprintf(f, "%s\n", input.c_str());
fclose(f);
}
int main(int argc, char** argv)
{
int i = 0;
while (true) {
write_txt_file("C:\\...\\Desktop\\out.txt", "Writing...#" + to_string(i));
Sleep(5000);
i++;
}
}
以下是我用来创建服务的命令:
sc.exe create My_service binPath= "<path to executable>" start= auto
并且out.txt
文件的输出为:
Writing...#0
Writing...#1
Writing...#2
Writing...#3
Writing...#4
Writing...#5
Writing...#6
Writing...#7
Writing...#8
答案 0 :(得分:3)
在@Aconcagua和this reference的帮助下,我找到了一个简单的代码,让我的代码与windows服务兼容。在函数ServiceWorkerThread
中,您需要将循环放在while块中。该服务可以安全停止。
#include <Windows.h>
#include <tchar.h>
#include <string>
#include <cstdio>
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("My Sample Service")
using namespace std;
void write_txt_file(string file_name, string input) {
/*
write a string to a specific txt file
*/
FILE *f = fopen(file_name.c_str(), "a+");
fprintf(f, "%s\n", input.c_str());
fclose(f);
}
int _tmain (int argc, TCHAR *argv[])
{
OutputDebugString(_T("My Sample Service: Main: Entry"));
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
{NULL, NULL}
};
if (StartServiceCtrlDispatcher (ServiceTable) == FALSE)
{
OutputDebugString(_T("My Sample Service: Main: StartServiceCtrlDispatcher returned error"));
return GetLastError ();
}
OutputDebugString(_T("My Sample Service: Main: Exit"));
return 0;
}
VOID WINAPI ServiceMain (DWORD argc, LPTSTR *argv)
{
DWORD Status = E_FAIL;
OutputDebugString(_T("My Sample Service: ServiceMain: Entry"));
g_StatusHandle = RegisterServiceCtrlHandler (SERVICE_NAME, ServiceCtrlHandler);
if (g_StatusHandle == NULL)
{
OutputDebugString(_T("My Sample Service: ServiceMain: RegisterServiceCtrlHandler returned error"));
goto EXIT;
}
// Tell the service controller we are starting
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)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
/*
* Perform tasks neccesary to start the service here
*/
OutputDebugString(_T("My Sample Service: ServiceMain: Performing Service Start Operations"));
// Create stop event to wait on later.
g_ServiceStopEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
if (g_ServiceStopEvent == NULL)
{
OutputDebugString(_T("My Sample Service: ServiceMain: CreateEvent(g_ServiceStopEvent) returned error"));
g_ServiceStatus.dwControlsAccepted = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwWin32ExitCode = GetLastError();
g_ServiceStatus.dwCheckPoint = 1;
if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
goto EXIT;
}
// Tell the service controller we are started
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)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
// Start the thread that will perform the main task of the service
HANDLE hThread = CreateThread (NULL, 0, ServiceWorkerThread, NULL, 0, NULL);
OutputDebugString(_T("My Sample Service: ServiceMain: Waiting for Worker Thread to complete"));
// Wait until our worker thread exits effectively signaling that the service needs to stop
WaitForSingleObject (hThread, INFINITE);
OutputDebugString(_T("My Sample Service: ServiceMain: Worker Thread Stop Event signaled"));
/*
* Perform any cleanup tasks
*/
OutputDebugString(_T("My Sample Service: ServiceMain: Performing Cleanup Operations"));
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)
{
OutputDebugString(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
EXIT:
OutputDebugString(_T("My Sample Service: ServiceMain: Exit"));
return;
}
VOID WINAPI ServiceCtrlHandler (DWORD CtrlCode)
{
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: Entry"));
switch (CtrlCode)
{
case SERVICE_CONTROL_STOP :
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: SERVICE_CONTROL_STOP Request"));
if (g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
break;
/*
* Perform tasks neccesary to stop the service here
*/
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)
{
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: SetServiceStatus returned error"));
}
// This will signal the worker thread to start shutting down
SetEvent (g_ServiceStopEvent);
break;
default:
break;
}
OutputDebugString(_T("My Sample Service: ServiceCtrlHandler: Exit"));
}
DWORD WINAPI ServiceWorkerThread (LPVOID lpParam)
{
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Entry"));
int i = 0;
// Periodically check if the service has been requested to stop
while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)
{
/*
* Perform main service function here
*/
//while (true) {
write_txt_file("C:\\...\\out.txt", "Writing...#" + to_string(i));
Sleep(5000);
i++;
// }
// Simulate some work by sleeping
Sleep(3000);
}
OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Exit"));
return ERROR_SUCCESS;
}
答案 1 :(得分:2)