创建Windows服务in C++

附录一:NTService.h
// ntservice.h
//
// Definitions for CNTService
//
#ifndef _NTSERVICE_H_
#define _NTSERVICE_H_
#include "ntservmsg.h" // Event message ids
#include <windows.h>
#include <stdio.h>
#include "Winsvc.h"
#define SERVICE_CONTROL_USER 128
class CNTService
{
public:
    CNTService(const char* szServiceName);
    virtual ~CNTService();
    BOOL ParseStandardArgs(int argc, char* argv[]);
    BOOL IsInstalled();
    BOOL Install();
    BOOL Uninstall();
 
    void LogEvent(WORD wType, DWORD dwID,
                  const char* pszS1 = NULL,
                  const char* pszS2 = NULL,
                  const char* pszS3 = NULL);
   
    BOOL StartService();
    void SetStatus(DWORD dwState);
    BOOL Initialize();
    virtual void Run();
 virtual BOOL OnInit();
    virtual void OnStop();
    virtual void OnInterrogate();
    virtual void OnPause();
    virtual void OnContinue();
    virtual void OnShutdown();
    virtual BOOL OnUserControl(DWORD dwOpcode);
    void DebugMsg(const char* pszFormat, ...);
   
    // static member functions
    static void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv);
    static void WINAPI Handler(DWORD dwOpcode);
    // data members
    char m_szServiceName[64];
    int m_iMajorVersion;
    int m_iMinorVersion;
    SERVICE_STATUS_HANDLE m_hServiceStatus;
    SERVICE_STATUS m_Status;
    BOOL m_bIsRunning;
    // static data
    static CNTService* m_pThis; // nasty hack to get object ptr
public:
    HANDLE m_hEventSource;

};
#endif // _NTSERVICE_H_
附录二:
// NTService.cpp
//
// Implementation of CNTService
#include "stdafx.h"
#include "NTService.h"

// static variables
CNTService* CNTService::m_pThis = NULL;
//HANDLE CNTService::m_hEventSource = NULL;

CNTService::CNTService(const char* szServiceName)
{
    // copy the address of the current object so we can access it from
    // the static member callback functions.
    // WARNING: This limits the application to only one CNTService object.
    m_pThis = this;
   
    // Set the default service name and version
 strncpy(m_szServiceName, szServiceName, sizeof(m_szServiceName)-1);
    m_iMajorVersion = 1;
    m_iMinorVersion = 0;
    m_hEventSource = NULL;
    // set up the initial service status
    m_hServiceStatus = NULL;
    m_Status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; //进程只有一个服务
    m_Status.dwCurrentState = SERVICE_STOPPED;//服务没有在运行
    m_Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;//可以停止服务
    m_Status.dwWin32ExitCode = 0;
    m_Status.dwServiceSpecificExitCode = 0;
    m_Status.dwCheckPoint = 0;
    m_Status.dwWaitHint = 0;
    m_bIsRunning = FALSE;
}
CNTService::~CNTService()
{
    DebugMsg("CNTService::~CNTService()");
    if (m_hEventSource) {
        ::DeregisterEventSource(m_hEventSource);
    }
}

// Default command line argument parsing
// Returns TRUE if it found an arg it recognised, FALSE if not
// Note: processing some arguments causes output to stdout to be generated.
BOOL CNTService::ParseStandardArgs(int argc, char* argv[])
{
    // See if we have any command line args we recognise
    if (argc <= 1) return FALSE;
    if (_stricmp(argv[1], "-v") == 0) {
        // Spit out version info
        printf("%s Version %d.%d\n",
               m_szServiceName, m_iMajorVersion, m_iMinorVersion);
        printf("The service is %s installed\n",
               IsInstalled() ? "currently" : "not");
        return TRUE; // say we processed the argument
    } else if (_stricmp(argv[1], "-i") == 0) {
        // Request to install.
        if (IsInstalled()) {
            printf("%s is already installed\n", m_szServiceName);
        } else {
            // Try and install the copy that's running
            if (Install()) {
                printf("%s installed\n", m_szServiceName);
            } else {
                printf("%s failed to install. Error %d\n", m_szServiceName, GetLastError());
            }
        }
        return TRUE; // say we processed the argument
    } else if (_stricmp(argv[1], "-u") == 0) {
        // Request to uninstall.
        if (!IsInstalled()) {
            printf("%s is not installed\n", m_szServiceName);
        } else {
            // Try and remove the copy that's installed
            if (Uninstall()) {
                // Get the executable file path
                char szFilePath[_MAX_PATH];
                ::GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
                printf("%s removed. (You must delete the file (%s) yourself.)\n",
                       m_szServiceName, szFilePath);
            } else {
                printf("Could not remove %s. Error %d\n", m_szServiceName, GetLastError());
            }
        }
        return TRUE; // say we processed the argument
   
    }
        
    // Don't recognise the args
    return FALSE;
}

// Install/uninstall routines
// Test if the service is currently installed
BOOL CNTService::IsInstalled()
{
    BOOL bResult = FALSE;
    // Open the Service Control Manager
    SC_HANDLE hSCM = ::OpenSCManager(NULL, // local machine
                                     NULL, // ServicesActive database
                                     SC_MANAGER_ALL_ACCESS); // full access
    if (hSCM) {
        // Try to open the service
        SC_HANDLE hService = ::OpenService(hSCM,
                                           m_szServiceName,
                                           SERVICE_QUERY_CONFIG);
        if (hService) {
            bResult = TRUE;
            ::CloseServiceHandle(hService);
        }
        ::CloseServiceHandle(hSCM);
    }
   
    return bResult;
}
BOOL CNTService::Install()
{
    // Open the Service Control Manager
    SC_HANDLE hSCM = ::OpenSCManager(NULL, // local machine
                                     NULL, // ServicesActive database
                                     SC_MANAGER_ALL_ACCESS); // full access
    if (!hSCM) return FALSE;
    // Get the executable file path
    char szFilePath[_MAX_PATH];
    ::GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
    // Create the service
    SC_HANDLE hService = ::CreateService(hSCM,
                                         m_szServiceName,
                                         m_szServiceName,
                                         SERVICE_ALL_ACCESS,
                                         SERVICE_WIN32_OWN_PROCESS,
                                         SERVICE_DEMAND_START,        // start condition
                                         SERVICE_ERROR_NORMAL,
                                         szFilePath,
                                         NULL,
                                         NULL,
                                         NULL,
                                         NULL,
                                         NULL);
 DWORD dwLastError = GetLastError();
    if (!hService) {
        ::CloseServiceHandle(hSCM);
        return FALSE;
    }
    // make registry entries to support logging messages
    // Add the source name as a subkey under the Application
    // key in the EventLog service portion of the registry.
    char szKey[256];
    HKEY hKey = NULL;
    strcpy(szKey, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\");
    strcat(szKey, m_szServiceName);
    if (::RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &hKey) != ERROR_SUCCESS) {
        ::CloseServiceHandle(hService);
        ::CloseServiceHandle(hSCM);
        return FALSE;
    }
    // Add the Event ID message-file name to the 'EventMessageFile' subkey.
    ::RegSetValueEx(hKey,
                    "EventMessageFile",
                    0,
                    REG_EXPAND_SZ,
                    (CONST BYTE*)szFilePath,
                    strlen(szFilePath) + 1);    
    // Set the supported types flags.
 //只支持错误、警告和信息三种消息
    DWORD dwData = EVENTLOG_SUCCESS | EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
    ::RegSetValueEx(hKey,
                    "TypesSupported",
                    0,
                    REG_DWORD,
                    (CONST BYTE*)&dwData,
                     sizeof(DWORD));
    ::RegCloseKey(hKey);
    LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_INSTALLED, m_szServiceName);
    // tidy up
    ::CloseServiceHandle(hService);
    ::CloseServiceHandle(hSCM);
    return TRUE;
}
BOOL CNTService::Uninstall()
{
    // Open the Service Control Manager
    SC_HANDLE hSCM = ::OpenSCManager(NULL, // local machine
                                     NULL, // ServicesActive database
                                     SC_MANAGER_ALL_ACCESS); // full access
    if (!hSCM) return FALSE;
    BOOL bResult = FALSE;
    SC_HANDLE hService = ::OpenService(hSCM,
                                       m_szServiceName,
                                       DELETE);
    if (hService) {
        if (::DeleteService(hService)) {
            LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_REMOVED, m_szServiceName);
            bResult = TRUE;
        } else {
            LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_NOTREMOVED, m_szServiceName);
        }
        ::CloseServiceHandle(hService);
    }
   
    ::CloseServiceHandle(hSCM);
    return bResult;
}
///
// Logging functions
// This function makes an entry into the application event log
void CNTService::LogEvent(WORD wType, DWORD dwID,
                          const char* pszS1,
                          const char* pszS2,
                          const char* pszS3)
{
    
    const char* ps[3];
    ps[0] = pszS1;
    ps[1] = pszS2;
    ps[2] = pszS3;
    int iStr = 0;
    for (int i = 0; i < 3; i++) {
        if (ps[i] != NULL) iStr++;
    }
       
    // Check the event source has been registered and if
    // not then register it now
    if (!m_hEventSource) {
        m_hEventSource = ::RegisterEventSource(NULL,  // local machine
                                               m_szServiceName); // source name
    }
    if (m_hEventSource) {
        ::ReportEvent(m_hEventSource,
                      wType,
                      0,
                      dwID,
                      NULL, // sid
                      iStr,
                      0,
                      ps,
                      NULL);
    }
}
//
// Service startup and registration
BOOL CNTService::StartService()
{
 SERVICE_TABLE_ENTRY st[] = {
  {_T(m_szServiceName), ServiceMain},
        {NULL, NULL}
    };
 
    DebugMsg("Calling StartServiceCtrlDispatcher()");
    BOOL b = ::StartServiceCtrlDispatcher(st);
 DWORD dwLastErr = GetLastError();
    DebugMsg("Returned from StartServiceCtrlDispatcher()");
    return b;
}
// static member function (callback)
void CNTService::ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
    // Get a pointer to the C++ object
    CNTService* pService = m_pThis;
   
    pService->DebugMsg("Entering CNTService::ServiceMain()");
    // Register the control request handler
    pService->m_Status.dwCurrentState = SERVICE_START_PENDING;
    pService->m_hServiceStatus = RegisterServiceCtrlHandler(pService->m_szServiceName,
                                                           Handler);
    if (pService->m_hServiceStatus == NULL) {
        pService->LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_CTRLHANDLERNOTINSTALLED);
        return;
    }
    // Start the initialisation
    if (pService->Initialize()) {
        // Do the real work.
        // When the Run function returns, the service has stopped.
        pService->m_bIsRunning = TRUE;
        pService->m_Status.dwWin32ExitCode = 0;
        pService->m_Status.dwCheckPoint = 0;
        pService->m_Status.dwWaitHint = 0;
        pService->Run();
    }
    // Tell the service manager we are stopped
    pService->SetStatus(SERVICE_STOPPED);
    pService->DebugMsg("Leaving CNTService::ServiceMain()");
}
///
// status functions
void CNTService::SetStatus(DWORD dwState)
{
    DebugMsg("CNTService::SetStatus(%lu, %lu)", m_hServiceStatus, dwState);
    m_Status.dwCurrentState = dwState;
    ::SetServiceStatus(m_hServiceStatus, &m_Status);
}
///
// Service initialization
BOOL CNTService::Initialize()
{
    DebugMsg("Entering CNTService::Initialize()");
    // Start the initialization
    SetStatus(SERVICE_START_PENDING);
   
    // Perform the actual initialization
    BOOL bResult = OnInit();
   
    // Set final state
    m_Status.dwWin32ExitCode = GetLastError();
    m_Status.dwCheckPoint = 0;
    m_Status.dwWaitHint = 0;
    if (!bResult) {
        LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_FAILEDINIT);
        SetStatus(SERVICE_STOPPED);
        return FALSE;   
    }
   
    //LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_STARTED);EVENTLOG_SUCCESS
 LogEvent(EVENTLOG_SUCCESS, EVMSG_STARTED);
    SetStatus(SERVICE_RUNNING);
    DebugMsg("Leaving CNTService::Initialize()");
    return TRUE;
}
///
// main function to do the real work of the service
// This function performs the main work of the service.
// When this function returns the service has stopped.
void CNTService::Run()
{
    DebugMsg("Entering CNTService::Run()");
    while (m_bIsRunning) {
        DebugMsg("Sleeping...");
        Sleep(5000);
    }
    // nothing more to do
    DebugMsg("Leaving CNTService::Run()");
}
//
// Control request handlers
// static member function (callback) to handle commands from the
// service control manager
void CNTService::Handler(DWORD dwOpcode)
{
    // Get a pointer to the object
    CNTService* pService = m_pThis;
   
    pService->DebugMsg("CNTService::Handler(%lu)", dwOpcode);
    switch (dwOpcode) {
    case SERVICE_CONTROL_STOP: // 1
        pService->SetStatus(SERVICE_STOP_PENDING);
        pService->OnStop();
        pService->m_bIsRunning = FALSE;
        pService->LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_STOPPED);
        break;
    case SERVICE_CONTROL_PAUSE: // 2
        pService->OnPause();
        break;
    case SERVICE_CONTROL_CONTINUE: // 3
        pService->OnContinue();
        break;
    case SERVICE_CONTROL_INTERROGATE: // 4
        pService->OnInterrogate();
        break;
    case SERVICE_CONTROL_SHUTDOWN: // 5
        pService->OnShutdown();
        break;
    default:
        if (dwOpcode >= SERVICE_CONTROL_USER) {
            if (!pService->OnUserControl(dwOpcode)) {
                pService->LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_BADREQUEST);
            }
        } else {
            pService->LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_BADREQUEST);
        }
        break;
    }
    // Report current status
    pService->DebugMsg("Updating status (%lu, %lu)",
                       pService->m_hServiceStatus,
                       pService->m_Status.dwCurrentState);
    ::SetServiceStatus(pService->m_hServiceStatus, &pService->m_Status);
}
       
// Called when the service is first initialized
BOOL CNTService::OnInit()
{
    DebugMsg("CNTService::OnInit()");
 return TRUE;
}
// Called when the service control manager wants to stop the service
void CNTService::OnStop()
{
    DebugMsg("CNTService::OnStop()");
}
// called when the service is interrogated
void CNTService::OnInterrogate()
{
    DebugMsg("CNTService::OnInterrogate()");
}
// called when the service is paused
void CNTService::OnPause()
{
    DebugMsg("CNTService::OnPause()");
}
// called when the service is continued
void CNTService::OnContinue()
{
    DebugMsg("CNTService::OnContinue()");
}
// called when the service is shut down
void CNTService::OnShutdown()
{
    DebugMsg("CNTService::OnShutdown()");
}
// called when the service gets a user control message
BOOL CNTService::OnUserControl(DWORD dwOpcode)
{
    DebugMsg("CNTService::OnUserControl(%8.8lXH)", dwOpcode);
    LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_SERVCTRL); 
    return FALSE; // say not handled
}


// Debugging support
void CNTService::DebugMsg(const char* pszFormat, ...)
{
    char buf[1024];
    sprintf(buf, "[%s](%lu): ", m_szServiceName, GetCurrentThreadId());
 va_list arglist;
 va_start(arglist, pszFormat);
    vsprintf(&buf[strlen(buf)], pszFormat, arglist);
 va_end(arglist);
    strcat(buf, "\n");
    OutputDebugString(buf);
}
其余代码较简单,本文不在列出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了在Windows上配置VS Code的C++开发环境,您可以按照以下步骤进行操作: 1. 安装Visual Studio Code:首先,您需要下载并安装Visual Studio Code编辑器。您可以在VS Code官方网站上下载对应的Windows版本并按照安装向导进行安装。 2. 安装C++编译器:Windows上默认并不包含C++编译器,因此您需要安装一个。推荐使用MinGW-w64,它是一个Windows上的开源软件包,提供了GCC编译器工具集。 - 访问MinGW-w64官方网站:https://mingw-w64.org/doku.php - 在“Downloads”页面中,选择适合您系统的最新版本,点击下载。 - 安装下载好的MinGW-w64。在安装过程中,确保选择“Architecture”为x86_64(64位系统)或i686(32位系统)。 - 在安装过程中,将安装路径添加到系统环境变量中。例如,如果您选择了默认路径,则将`C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0`或`C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0`添加到PATH环境变量。 3. 安装C++插件:打开VS Code并在左侧导航栏中选择“Extensions”图标。搜索并安装"C/C++"插件,这是由Microsoft提供的官方插件,用于C++开发。 4. 配置编译器路径:在VS Code中,按下`Ctrl + Shift + P`打开命令面板,然后输入“C/C++: Edit Configurations(编辑配置)”。选择"Edit Configurations in c_cpp_properties.json(在c_cpp_properties.json中编辑配置)"。 在json文件中,找到`"compilers"`部分,并添加以下内容来配置MinGW-w64编译器的路径: ```json "compilerPath": "C:\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin\\g++.exe", "cStandard": "c17", "cppStandard": "c++17" ``` 请注意,`compilerPath`可能因为您选择的MinGW-w64版本和安装路径而有所不同。确保使用正确的路径。 5. 创建C++项目:在VS Code中,选择“File”菜单,然后选择“Open Folder”以打开您的C++项目文件夹。在文件夹中,创建一个新的.cpp文件或打开现有的.cpp文件。 6. 编写和运行代码:在打开的.cpp文件中编写您的C++代码。按下`Ctrl + Shift + B`编译代码。选择“g++.exe build active file”来构建并生成可执行文件。按下F5键或选择调试菜单中的“Start Debugging”来启动调试会话。 希望这些步骤能够帮助您在Windows上成功配置VS Code的C++环境。如果您在配置过程中遇到任何问题,请随时向我提问!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值