msdn中windows service例子

来源:互联网 发布:网络赚钱 编辑:程序博客网 时间:2024/05/18 04:03

http://code.msdn.microsoft.com/CppWindowsService-74bb412c

 

A basic Windows service in C++ (CppWindowsService)

This code sample demonstrates creating a basic Windows Service application in VC++

C++ (777.9 KB)
 

SERVICE APPLICATION (CppWindowsService)

Introduction

This code sample demonstrates creating a very basic Windows Service application in Visual C++. Theexample Windows Service logs the service start and stop information to the Application event log, and shows how to run the main function of the service in a thread pool worker thread. You can easily extend the Windows Service skeleton to meet your own business requirement.

Running the Sample

The following steps walk through a demonstration of the Windows Service sample.

Step1. After you successfully build the sample project in Visual Studio 2010, you will get a service application: CppWindowsService.exe.

Step2. Run a command prompt as administrator, navigate to the output folder of the sample project, and enter the following command to install the service.

  CppWindowsService.exe -install

The service is successfully installed if the process outputs:

If you do not see this output, please look for error codes in theouput, and investigate the cause of failure. For example, the error code 0x431 means that the service already exists, and you need to uninstall it first.

Step3. Open Service Management Console (services.msc). You should be able to find "CppWindowsService Sample Service" in the service list.

Step4. Right-click the CppWindowsService service in Service Management Console and select Start to start the service. Open Event Viewer, and navigate to Windows Logs / Application. You should be able to see this event from CppWindowsService with the information:

Step5. Right-click the service in Service Management Console and select Stop to stop the service. You will see this new event fromCppWindowsService in Event Viewer / Windows Logs / Application with the information:

Step6. To uninstall the service, enter the following command in the command prompt running as administrator.

  CppWindowsService.exe -remove

If the service is successfully removed, you would see this output:

Using the Code

Step1. In Visual Studio 2010, add a new Visual C++ / Win32 / Win32 Console Application project namedCppWindowsService. Unselect the "Precompiled header" option in Application Settings of the Win32 Application Wizard, and delete stdafx.h, stdafx.cpp, targetver.h files after the project is created.

Step2. Define the settings of the service in CppWindowsService.cpp.

Copy code
C++
Edit|Remove
// Internal name of the service    #define SERVICE_NAME             L"CppWindowsService"      // Displayed name of the service    #define SERVICE_DISPLAY_NAME     L"CppWindowsService Sample Service"      // Service start options.    #define SERVICE_START_TYPE       SERVICE_DEMAND_START      // List of service dependencies - "dep1\0dep2\0\0"    #define SERVICE_DEPENDENCIES     L""      // The name of the account under which the service should run    #define SERVICE_ACCOUNT          L"NT AUTHORITY\\LocalService"      // The password to the service account name    #define SERVICE_PASSWORD         NULL  

Security Note: In this code sample, the service is configured to run asLocalService, instead of LocalSystem. The LocalSystem account has broad permissions. Use the LocalSystem account with caution, because it might increase your risk of attacks from malicious software. For tasks that do not need broad permissions, consider using the LocalService account, which acts as a non-privileged user on the local computer and presents anonymous credentials to any remote server.

Step3. Replace the application's entry point (main) in CppWindowsService.cpp with the code below. According to the arguments in the command line, the function installs or uninstalls or starts the service by calling into different routines that will be declared and implemented in the next steps

Copy code
C++
Edit|Remove
int wmain(int argc, wchar_t *argv[])     {         if ((argc > 1) && ((*argv[1] == L'-' || (*argv[1] == L'/'))))         {             if (_wcsicmp(L"install", argv[1] + 1) == 0)             {                 // Install the service when the command is                  // "-install" or "/install".                 InstallService(                     SERVICE_NAME,               // Name of service                     SERVICE_DISPLAY_NAME,       // Name to display                     SERVICE_START_TYPE,         // Service start type                     SERVICE_DEPENDENCIES,       // Dependencies                     SERVICE_ACCOUNT,            // Service running account                     SERVICE_PASSWORD            // Password of the account                     );             }             else if (_wcsicmp(L"remove", argv[1] + 1) == 0)             {                 // Uninstall the service when the command is                  // "-remove" or "/remove".                 UninstallService(SERVICE_NAME);             }         }         else         {             wprintf(L"Parameters:\n");             wprintf(L" -install  to install the service.\n");             wprintf(L" -remove   to remove the service.\n");               CSampleService service(SERVICE_NAME);             if (!CServiceBase::Run(service))             {                 wprintf(L"Service failed to run w/err 0x%08lx\n", GetLastError());             }         }           return 0;     }  

Step4. Add the ServiceBase.h and ServiceBase.cpp files to provide a base class for a service that will exist as part of a service application. The class is named "CServiceBase". It must be derived from when creating a new service class.

The service base class has these public functions:

Copy code
C++
Edit|Remove
// It register the executable for a service with SCM.   static BOOL CServiceBase::Run(CServiceBase &service)     // This is the constructor of the service class. The optional parameters    // (fCanStop, fCanShutdown and fCanPauseContinue) allow you to specify    // whether the service can be stopped, paused and continued, or be    // notified when system shutdown occurs.   CServiceBase::CServiceBase(PWSTR pszServiceName,        BOOL fCanStop = TRUE,        BOOL fCanShutdown = TRUE,        BOOL fCanPauseContinue = FALSE)     // This is the virtual destructor of the service class.   virtual ~CServiceBase::CServiceBase(void);      // Funtion that stops the service.   void CServiceBase::Stop();  

The class also provides these virtual member functions. You can implement them in a derived class. The functions execute when the service starts, stops, pauses, resumes, and when the system is shutting down.

Copy code
C++
Edit|Remove
virtual void OnStart(DWORD dwArgc, PWSTR *pszArgv);  virtual void OnStop();  virtual void OnPause();  virtual void OnContinue();  virtual void OnShutdown();  

Step5. Add the SampleService.h and SampleService.cpp files to provide a sample service class that derives from the service base class - CServiceBase. The sampleservice logs the service start and stop information to the Application log, and shows how to run the main function of the service in a thread pool worker thread.

CSampleService::OnStart, which is executed when the service starts, callsCServiceBase::WriteEventLogEntry to log the service-start information. And it calls CThreadPool::QueueUserWorkItem to queue the main service function (CSampleService::ServiceWorkerThread) for execution in a worker thread.

NOTE: A service application is designed to be long running. Therefore, it usually polls or monitors something in the system. The monitoring is set up in theOnStart method. However, OnStart does not actually do the monitoring. The OnStart method must return to the operating system after the service's operation has begun. It must not loop forever or block. To set up a simple monitoring mechanism, one general solution is to create a timer in OnStart. The timer would then raise events in your code periodically, at which time your service could do its monitoring. The other solution is to spawn a new

thread to perform the main service functions, which is demonstrated in this code sample.

Copy code
C++
Edit|Remove
void CSampleService::OnStart(DWORD dwArgc, LPWSTR *lpszArgv)    {        // Log a service start message to the Application log.        WriteEventLogEntry(L"CppWindowsService in OnStart",             EVENTLOG_INFORMATION_TYPE);          // Queue the main service function for execution in a worker thread.        CThreadPool::QueueUserWorkItem(&CSampleService::ServiceWorkerThread, this);    }  

CSampleService::OnStop, which is executed when the service stops, callsCServiceBase::WriteEventLogEntry to log the service-stop information. Next, it sets the member varaible m_fStopping as TRUE to indicate that the service is stopping and waits for the finish of the main service function that is signaled by the m_hStoppedEvent event object.

Copy code
C++
Edit|Remove
void CSampleService::OnStop()    {        WriteEventLogEntry(L"CppWindowsService in OnStop",             EVENTLOG_INFORMATION_TYPE);          // Indicate that the service is stopping and wait for the finish of the         // main service function (ServiceWorkerThread).        m_fStopping = TRUE;        if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)        {            throw GetLastError();        }    }  

CSampleService::ServiceWorkerThread runs in a thread pool worker thread. It performs the main function of the service such as the communication with client applications through a named pipe. In order that the main function finishes gracefully when the service is about to stop, it should periodically check the m_fStopping varaible. When the function detects that the service is stopping, it cleans up the work and signal the m_hStoppedEvent event object.

Copy code
C++
Edit|Remove
void CSampleService::ServiceWorkerThread(void)    {        // Periodically check if the service is stopping.        while (!m_fStopping)        {            // Perform main service function here...              ::Sleep(2000);  // Simulate some lengthy operations.        }          // Signal the stopped event.        SetEvent(m_hStoppedEvent);    }  

Step6. Add the ServiceInstaller.h and ServiceInstaller.cpp files to declare and implement functions that install and uninstall the service:

Copy code
C++
Edit|Remove
InstallService          Installs the service UninstallService        Uninstalls the service   

 

 

#include"XXXX.h"  //包含的头文件 //定义全局函数变量void Init();BOOL IsInstalled();BOOL Install();BOOL Uninstall();void LogEvent(LPCTSTR pszFormat, ...);void WINAPI ServiceMain();void WINAPI ServiceStrl(DWORD dwOpcode); TCHAR szServiceName[] = _T("WatchDog");BOOL bInstall;SERVICE_STATUS_HANDLE hServiceStatus;SERVICE_STATUS status;DWORD dwThreadID; int APIENTRY WinMain(HINSTANCE hInstance,                     HINSTANCE hPrevInstance,                     LPSTR     lpCmdLine,                     int       nCmdShow){    Init();     dwThreadID = ::GetCurrentThreadId();     SERVICE_TABLE_ENTRY st[] =    {        { szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },        { NULL, NULL }    };     if (stricmp(lpCmdLine, "/install") == 0)        {           Install();        }    else if (stricmp(lpCmdLine, "/uninstall") == 0)        {            Uninstall();        }    else        {         if (!::StartServiceCtrlDispatcher(st))        {            LogEvent(_T("Register Service Main Function Error!"));        }      }     return 0;}//*********************************************************//Functiopn:            Init//Description:          初始化//Calls:                main       //          <author>niying <time>2006-8-10      <version>     <desc>//*********************************************************void Init(){    hServiceStatus = NULL;    status.dwServiceType = SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;    status.dwCurrentState = SERVICE_START_PENDING;    status.dwControlsAccepted = SERVICE_ACCEPT_STOP;    status.dwWin32ExitCode = 0;    status.dwServiceSpecificExitCode = 0;    status.dwCheckPoint = 0;    status.dwWaitHint = 0;} //*********************************************************//Functiopn:            ServiceMain//Description:          服务主函数,这在里进行控制对服务控制的注册//          <author>niying <time>2006-8-10      <version>     <desc>//*********************************************************void WINAPI ServiceMain(){    // Register the control request handler    status.dwCurrentState = SERVICE_START_PENDING;    status.dwControlsAccepted = SERVICE_ACCEPT_STOP;     //注册服务控制    hServiceStatus = RegisterServiceCtrlHandler(szServiceName, ServiceStrl);    if (hServiceStatus == NULL)    {        LogEvent(_T("Handler not installed"));        return;    }    SetServiceStatus(hServiceStatus, &status);     status.dwWin32ExitCode = S_OK;    status.dwCheckPoint = 0;    status.dwWaitHint = 0;    status.dwCurrentState = SERVICE_RUNNING;    SetServiceStatus(hServiceStatus, &status);     //模拟服务的运行。应用时将主要任务放于此即可        //可在此写上服务需要执行的代码,一般为死循环      while(1)    {           //循环干什么     }       status.dwCurrentState = SERVICE_STOPPED;    SetServiceStatus(hServiceStatus, &status);    OutputDebugString(_T("Service stopped"));} //*********************************************************//Functiopn:            ServiceStrl//Description:          服务控制主函数,这里实现对服务的控制,//                      当在服务管理器上停止或其它操作时,将会运行此处代码//Calls://Called By://Table Accessed://Table Updated://Input:                dwOpcode:控制服务的状态//Output://Return://Others://History://          <author>niying <time>2006-8-10      <version>     <desc>//*********************************************************void WINAPI ServiceStrl(DWORD dwOpcode){    switch (dwOpcode)    {    case SERVICE_CONTROL_STOP:        status.dwCurrentState = SERVICE_STOP_PENDING;        SetServiceStatus(hServiceStatus, &status);        PostThreadMessage(dwThreadID, WM_CLOSE, 0, 0);        break;    case SERVICE_CONTROL_PAUSE:        break;    case SERVICE_CONTROL_CONTINUE:        break;    case SERVICE_CONTROL_INTERROGATE:        break;    case SERVICE_CONTROL_SHUTDOWN:        break;    default:        LogEvent(_T("Bad service request"));        OutputDebugString(_T("Bad service request"));    }}//*********************************************************//Functiopn:            IsInstalled//Description:          判断服务是否已经被安装//          <author>niying <time>2006-8-10      <version>     <desc>//*********************************************************BOOL IsInstalled(){    BOOL bResult = FALSE;     //打开服务控制管理器    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);     if (hSCM != NULL)    {        //打开服务        SC_HANDLE hService = ::OpenService(hSCM, szServiceName, SERVICE_QUERY_CONFIG);        if (hService != NULL)        {            bResult = TRUE;            ::CloseServiceHandle(hService);        }          ::CloseServiceHandle(hSCM);    }    return bResult;} //*********************************************************//Functiopn:            Install//Description:          安装服务函数//          <author>niying <time>2006-8-10      <version>     <desc>//*********************************************************BOOL Install(){    if (IsInstalled())        return TRUE;     //打开服务控制管理器    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);    if (hSCM == NULL)    {        MessageBox(NULL, _T("Couldn't open service manager"), szServiceName, MB_OK);        return FALSE;    }     // Get the executable file path    TCHAR szFilePath[MAX_PATH];    ::GetModuleFileName(NULL, szFilePath, MAX_PATH);     //创建服务    SC_HANDLE hService = ::CreateService(hSCM, szServiceName, szServiceName,        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS ,SERVICE_AUTO_START , SERVICE_ERROR_NORMAL,        szFilePath, NULL, NULL, _T(""), NULL, NULL);     if (hService == NULL)    {        ::CloseServiceHandle(hSCM);        MessageBox(NULL, _T("Couldn't create service"), szServiceName, MB_OK);        return FALSE;    }     ::CloseServiceHandle(hService);    ::CloseServiceHandle(hSCM);    return TRUE;} //*********************************************************//Functiopn:            Uninstall//Description:          删除服务函数//          <author>niying <time>2006-8-10      <version>     <desc>//*********************************************************BOOL Uninstall(){    if (!IsInstalled())        return TRUE;     SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);     if (hSCM == NULL)    {        MessageBox(NULL, _T("Couldn't open service manager"), szServiceName, MB_OK);        return FALSE;    }     SC_HANDLE hService = ::OpenService(hSCM, szServiceName, SERVICE_STOP | DELETE);     if (hService == NULL)    {        ::CloseServiceHandle(hSCM);        MessageBox(NULL, _T("Couldn't open service"), szServiceName, MB_OK);        return FALSE;    }    SERVICE_STATUS status;    ::ControlService(hService, SERVICE_CONTROL_STOP, &status);     //删除服务    BOOL bDelete = ::DeleteService(hService);    ::CloseServiceHandle(hService);    ::CloseServiceHandle(hSCM);     if (bDelete)        return TRUE;     LogEvent(_T("Service could not be deleted"));    return FALSE;} //*********************************************************//Functiopn:            LogEvent//Description:          记录服务事件//          <author>niying <time>2006-8-10      <version>     <desc>//*********************************************************void LogEvent(LPCTSTR pFormat, ...){    TCHAR    chMsg[256];    HANDLE  hEventSource;    LPTSTR  lpszStrings[1];    va_list pArg;     va_start(pArg, pFormat);    _vstprintf(chMsg, pFormat, pArg);    va_end(pArg);     lpszStrings[0] = chMsg;         hEventSource = RegisterEventSource(NULL, szServiceName);    if (hEventSource != NULL)    {        ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);        DeregisterEventSource(hEventSource);    }}


 

0 0
原创粉丝点击