C++ 从已编译的应用程序创建windows服务

C++ 从已编译的应用程序创建windows服务,c++,c,windows,service,C++,C,Windows,Service,我想使用Microsoft Visual Studio 2015通过编译的C/C++代码创建服务。我编译了我的代码,并使用app executable中的sc.exe创建了一个服务。我的代码由一个无休止的循环组成,它在时间间隔内将一个简单的字符串写入一个静态文件。创建服务并重新启动后,服务似乎会自动停止。直接运行时,可执行文件工作正常 代码如下: #include "stdafx.h" #include <string> #include <cstdio> #includ

我想使用Microsoft Visual Studio 2015通过编译的C/C++代码创建服务。我编译了我的代码,并使用app executable中的
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++;
    }
}

Windows服务不仅仅是您编写的简单可执行文件,还需要遵循特定的模式来与操作系统通信。你们可以在网站上找到所有必要的信息,此外,任何一个好的搜索引擎都会显示出无数的例子,比如

或者,您也可以使用windows服务包装器(您可以尝试——尽管需要说,我没有对其进行评估——或者搜索另一个合适的包装器)


旁注:为什么您的可执行文件停止执行?嗯,因为它没有遵循上面提到的模式,我。E没有适当地通知操作系统其状态(参见链接),因此被操作系统再次关闭(终止),因为它认为您的“服务”不可操作…

Windows服务不仅仅是您编写的简单可执行文件,还需要遵循特定模式如何与操作系统通信。你们可以在网站上找到所有必要的信息,此外,任何一个好的搜索引擎都会显示出无数的例子,比如

或者,您也可以使用windows服务包装器(您可以尝试——尽管需要说,我没有对其进行评估——或者搜索另一个合适的包装器)


旁注:为什么您的可执行文件停止执行?嗯,因为它没有遵循上面提到的模式,我。E没有适当地通知操作系统它的状态(参见链接),因此被操作系统再次关闭(终止),因为它认为您的“服务”无法运行…

在@Aconcagua的帮助下,我找到了一个简单的代码,使我的代码与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;
}
#包括
#包括
#包括
#包括
服务状态g服务状态={0};
服务状态句柄g状态句柄=NULL;
HANDLE g\u ServiceStopEvent=无效的\u句柄\u值;
VOID WINAPI ServiceMain(DWORD argc,LPTSTR*argv);
作废WINAPI服务CtrlHandler(DWORD);
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
#定义服务名称(“我的示例服务”)
使用名称空间std;
无效写入txt文件(字符串文件名,字符串输入){
/*
将字符串写入特定的txt文件
*/
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(“我的示例服务:Main:Entry”);
服务表条目服务表[]=
{
{SERVICE_NAME,(LPSERVICE_MAIN_函数)ServiceMain},
{NULL,NULL}
};
如果(StartServiceCtrlDispatcher(ServiceTable)=FALSE)
{
OutputDebugString(_T(“我的示例服务:Main:StartServiceCtrlDispatcher返回错误”);
返回GetLastError();
}
OutputDebugString(_T(“我的示例服务:Main:Exit”);
返回0;
}
VOID WINAPI ServiceMain(DWORD argc,LPTSTR*argv)
{
DWORD状态=E_故障;
OutputDebugString(_T(“我的示例服务:ServiceMain:Entry”);
g_StatusHandle=RegisterServiceCtrlHandler(服务名称,ServiceCtrlHandler);
if(g_StatusHandle==NULL)
{
OutputDebugString(_T(“我的示例服务:ServiceMain:RegisterServiceCtrlHandler返回错误”);
转到出口;
}
//告诉服务控制员我们正在启动
零内存(&g_ServiceStatus,sizeof(g_ServiceStatus));
g_ServiceStatus.dwServiceType=SERVICE_WIN32_OWN_进程;
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_状态句柄和g_服务状态)==FALSE)
{
OutputDebugString(_T(“我的示例服务:ServiceMain:SetServiceStatus返回错误”);
}
/* 
*在此处执行启动服务所需的任务
*/
OutputDebugString(_T(“我的示例服务:ServiceMain:正在执行服务启动操作”);
//创建停止事件以稍后等待。
g_ServiceStopEvent=CreateEvent(NULL、TRUE、FALSE、NULL);
if(g_ServiceStopEvent==NULL)
{
OutputDebugString(_T(“我的示例服务:ServiceMain:CreateEvent(g_ServiceStopEvent)返回错误”);
g_ServiceStatus.dwControlsAccepted=0;
g_ServiceStatus.dwCurrentState=服务已停止;
g_ServiceStatus.dwWin32ExitCode=GetLastError();
g_ServiceStatus.dwCheckPoint=1;
if(SetServiceStatus(g_状态句柄和g_服务状态)==FALSE)
{
OutputDebugString(_T(“我的示例服务:ServiceMain:SetServiceStatus返回错误”);
}
转到出口;
}    
//告诉服务控制员我们已启动
g_ServiceStatus.dwControlsAccepted=服务接受停止;
g_ServiceStatus.dwCurrentState=服务运行;
g_ServiceStatus.dwWin32ExitCode=0;
g_ServiceStatus.dwCheckPoint=0;
if(SetServiceStatus(g_状态句柄和g_服务状态)==FALSE)
{
OutputDebugString(_T(“我的示例服务:ServiceMain:SetServiceStatus返回错误”);
}
//启动将执行服务主任务的线程
HANDLE hThread=CreateThread(NULL,0,ServiceWorkerThread,NULL,0,NULL);
OutputDebugString(_T(“我的示例服务:ServiceMain:正在等待工作线程完成”);
//等我们的工人回来
Writing...#0
Writing...#1
Writing...#2
Writing...#3
Writing...#4
Writing...#5
Writing...#6
Writing...#7
Writing...#8
#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;
}