Win8上Service程式及外部App調用此Service

來源:互聯網
上載者:User

標籤:des   style   blog   class   code   tar   

一.Service

藉助MSDN上Win7 Service的Demo和《用VC++建立Service服務應用程式》,在Win8上經曆各種磨難,終於跑起來自己改裝的服務程式了。

原來API基本沒變,我所困惑的是Win7上直接運行都沒有問題,在Win8上不可以。

報錯:

OpenSCManager failed w/err 0x00000005

原來是Win8上許可權的問題,也許我自己的Win7一啟動就擁有了Admin許可權吧。


下面直接進入正題,我整合了一下代碼,共三個檔案:main.c,Service.h, Service.cpp。(項目是控制台程式。)

main.c只是程式的入口,運行時接受參數。

#pragma region "Includes"#include <stdio.h>#include <windows.h>#include "Service.h"#pragma endregionint wmain(int argc, wchar_t* argv[]){if ((argc > 1) && ((*argv[1] == L‘-‘ || (*argv[1] == L‘/‘)))){if (_wcsicmp(L"install", argv[1] + 1) == 0){SvcInstall();}else if (_wcsicmp(L"remove", argv[1] + 1) == 0){SvcUninstall();}else if (_wcsicmp(L"query", argv[1] + 1) == 0){SvcQueryConfig();}        else if(_wcsicmp(L"start",argv[1] + 1) == 0)        {            SvcStart();         }        else if(_wcsicmp(L"stop",argv[1] + 1) == 0)        {            SvcStopNow();         }}else{_putws(L"Parameters:");_putws(L" -install    to install the service (require admin permission)");_putws(L" -remove     to remove the service (require admin permission)");_putws(L" -query      to query the configuration of the service");                _putws(L" -start      to start the service");                _putws(L" -stop       to stop the service");RunService();}return 0;}

代碼中已經寫的很清楚了,我的項目名稱為Win8Service,只要運行Win8Service.exe -install,服務就會被安裝。

注意:cmd必須要用admin啟動。win8下做法:WIN+Q鍵,開啟Search panel,輸入cmd,右擊Command Prompt,選擇Run as administrator。


下面看看這幾個函數的實現:

Service.h

#pragma once// Internal name of the service#define SERVICE_NAME             L"CppWin8Service"// Displayed name of the service#define SERVICE_DISPLAY_NAME     L"CppWin8Service Demo"// 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         NULLVOID RunService();VOID SvcInstall();VOID SvcUninstall();VOID SvcQueryConfig();BOOL SvcStart();VOID SvcStopNow();


Service.cpp

#pragma region "Includes"#include <stdio.h>#include <windows.h>#include "Service.h"#pragma endregionSERVICE_STATUS          g_ssSvcStatus;         // Current service statusSERVICE_STATUS_HANDLE   g_sshSvcStatusHandle;  // Current service status handleHANDLE                  g_hSvcStopEvent;VOID WINAPI SvcMain(DWORD dwArgc, LPWSTR* lpszArgv);VOID WINAPI SvcCtrlHandler(DWORD dwCtrl);VOID SvcInit(DWORD dwArgc, LPWSTR* lpszArgv);VOID SvcStop();VOID SvcReportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);VOID SvcReportEvent(LPWSTR lpszFunction, DWORD dwErr = 0);VOID RunService(){// You can add any additional services for the process to this table.SERVICE_TABLE_ENTRY dispatchTable[] = {{ SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)SvcMain }, { NULL, NULL }};// This call returns when the service has stopped.// The process should simply terminate when the call returns.if (!StartServiceCtrlDispatcher(dispatchTable)){SvcReportEvent(L"StartServiceCtrlDispatcher", GetLastError());}}VOID WINAPI SvcMain(DWORD dwArgc, LPWSTR* lpszArgv){SvcReportEvent(L"Enter SvcMain");// Register the handler function for the serviceg_sshSvcStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, SvcCtrlHandler);if (!g_sshSvcStatusHandle){SvcReportEvent(L"RegisterServiceCtrlHandler", GetLastError());return; } // These SERVICE_STATUS members remain as set hereg_ssSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_ssSvcStatus.dwServiceSpecificExitCode = 0;// Report initial status to the SCMSvcReportStatus(SERVICE_START_PENDING, NO_ERROR, 3000);// Perform service-specific initialization and work.SvcInit(dwArgc, lpszArgv);}VOID WINAPI SvcCtrlHandler(DWORD dwCtrl){// Handle the requested control code.switch(dwCtrl) {  case SERVICE_CONTROL_STOP: // Stop the service// SERVICE_STOP_PENDING should be reported before setting the Stop // Event - g_hSvcStopEvent - in SvcStop(). This avoids a race // condition which may result in a 1053 - The Service did not // respond... error.SvcReportStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);SvcStop();SvcReportStatus(g_ssSvcStatus.dwCurrentState, NO_ERROR, 0);return;case SERVICE_CONTROL_INTERROGATE: break; default:break;} }VOID SvcInit(DWORD dwArgc, LPWSTR* lpszArgv){SvcReportEvent(L"Enter SvcInit");/////////////////////////////////////////////////////////////////////////// Service initialization.// // Declare and set any required variables. Be sure to periodically call // ReportSvcStatus() with SERVICE_START_PENDING. If initialization fails, // call ReportSvcStatus with SERVICE_STOPPED.// Create a manual-reset event that is not signaled at first. The control // handler function, SvcCtrlHandler, signals this event when it receives // the stop control code.g_hSvcStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);if (g_hSvcStopEvent == NULL){SvcReportStatus(SERVICE_STOPPED, NO_ERROR, 0);return;}// Report running status when initialization is complete.SvcReportStatus(SERVICE_RUNNING, NO_ERROR, 0);/////////////////////////////////////////////////////////////////////////// Perform work until service stops.// while(TRUE){// Perform work ...// Check whether to stop the service.WaitForSingleObject(g_hSvcStopEvent, INFINITE);SvcReportStatus(SERVICE_STOPPED, NO_ERROR, 0);return;}}VOID SvcStop(){SvcReportEvent(L"Enter SvcStop");// Signal the service to stop.if (g_hSvcStopEvent){SetEvent(g_hSvcStopEvent);}}VOID SvcReportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,  DWORD dwWaitHint){static DWORD dwCheckPoint = 1;// Fill in the SERVICE_STATUS structure.g_ssSvcStatus.dwCurrentState = dwCurrentState;g_ssSvcStatus.dwWin32ExitCode = dwWin32ExitCode;g_ssSvcStatus.dwWaitHint = dwWaitHint;g_ssSvcStatus.dwControlsAccepted = (dwCurrentState == SERVICE_START_PENDING) ? 0 : SERVICE_ACCEPT_STOP;g_ssSvcStatus.dwCheckPoint = ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED)) ? 0 : dwCheckPoint++;// Report the status of the service to the SCM.SetServiceStatus(g_sshSvcStatusHandle, &g_ssSvcStatus);}VOID SvcReportEvent(LPWSTR lpszFunction, DWORD dwErr) {HANDLE hEventSource;LPCWSTR lpszStrings[2];wchar_t szBuffer[80];hEventSource = RegisterEventSource(NULL, SERVICE_NAME);if (NULL != hEventSource){WORD wType;if (dwErr == 0){swprintf_s(szBuffer, ARRAYSIZE(szBuffer), lpszFunction);wType = EVENTLOG_INFORMATION_TYPE;}else{swprintf_s(szBuffer, ARRAYSIZE(szBuffer), L"%s failed w/err 0x%08lx", lpszFunction, dwErr);wType = EVENTLOG_ERROR_TYPE;}lpszStrings[0] = SERVICE_NAME;lpszStrings[1] = szBuffer;ReportEvent(hEventSource,  // Event log handlewType,                 // Event type0,                     // Event category0,                     // Event identifierNULL,                  // No security identifier2,                     // Size of lpszStrings array0,                     // No binary datalpszStrings,           // Array of stringsNULL);                 // No binary dataDeregisterEventSource(hEventSource);}}VOID SvcInstall(){wchar_t szPath[MAX_PATH];if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) == 0){wprintf(L"GetModuleFileName failed w/err 0x%08lx\n", GetLastError());return;}// Open the local default service control manager databaseSC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);if (!schSCManager){wprintf(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError());return;}// Install the service into SCM by calling CreateServiceSC_HANDLE schService = CreateService(schSCManager,                   // SCManager databaseSERVICE_NAME,                   // Name of serviceSERVICE_DISPLAY_NAME,           // Name to displaySERVICE_CHANGE_CONFIG,          // Desired accessSERVICE_WIN32_OWN_PROCESS,      // Service typeSERVICE_DEMAND_START,           // Start typeSERVICE_ERROR_NORMAL,           // Error control typeszPath,                         // Service‘s binaryNULL,                           // No load ordering groupNULL,                           // No tag identifierSERVICE_DEPENDENCIES,           // DependenciesSERVICE_ACCOUNT,                // Service running accountSERVICE_PASSWORD);              // Password of the accountif (NULL != schService){wprintf(L"%s installed.\n", SERVICE_DISPLAY_NAME);CloseServiceHandle(schService);}else{wprintf(L"CreateService failed w/err 0x%08lx\n", GetLastError());}CloseServiceHandle(schSCManager);}VOID SvcUninstall(){// Open the local default service control manager databaseSC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);if (!schSCManager){wprintf(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError());return;}// Open the service with delete, stop and query status permissionsSC_HANDLE schService = OpenService(schSCManager, SERVICE_NAME, DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS);if (NULL != schService){// Try to stop the serviceSERVICE_STATUS ssSvcStatus;if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus)){wprintf(L"Stopping %s.", SERVICE_DISPLAY_NAME);Sleep(1000);while (QueryServiceStatus(schService, &ssSvcStatus)){if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING){wprintf(L".");Sleep(1000);}else break;}if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED){wprintf(L"\n%s stopped.\n", SERVICE_DISPLAY_NAME);}else{wprintf(L"\n%s failed to stop.\n", SERVICE_DISPLAY_NAME);}}// Now remove the service by calling DeleteServiceif (DeleteService(schService)){wprintf(L"%s removed.\n", SERVICE_DISPLAY_NAME);}else{wprintf(L"DeleteService failed w/err 0x%08lx\n", GetLastError());}CloseServiceHandle(schService);}else{wprintf(L"OpenService failed w/err 0x%08lx\n", GetLastError());}CloseServiceHandle(schSCManager);}VOID SvcQueryConfig(){// Open the local default service control manager databaseSC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);if (!schSCManager){wprintf(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError());return;}// Try to open the service to query its status and configSC_HANDLE schService = OpenService(schSCManager, SERVICE_NAME, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);if (NULL != schService){wprintf(L"%s was installed.\n", SERVICE_DISPLAY_NAME);DWORD cbBytesNeeded;// // Query the status of the service// SERVICE_STATUS_PROCESS ssp;if (QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(ssp), &cbBytesNeeded)){wprintf(L"Service status: ");switch (ssp.dwCurrentState){case SERVICE_STOPPED: _putws(L"Stopped"); break;case SERVICE_RUNNING: _putws(L"Running"); break;case SERVICE_PAUSED: _putws(L"Paused"); break;case SERVICE_START_PENDING:case SERVICE_STOP_PENDING:case SERVICE_CONTINUE_PENDING:case SERVICE_PAUSE_PENDING: _putws(L"Pending"); break;}}else{wprintf(L"QueryServiceStatusEx failed w/err 0x%08lx\n", GetLastError());}CloseServiceHandle(schService);}else{DWORD dwErr = GetLastError();if (dwErr == ERROR_SERVICE_DOES_NOT_EXIST){wprintf(L"%s was not installed.\n", SERVICE_DISPLAY_NAME);}else{wprintf(L"OpenService failed w/err 0x%08lx\n", dwErr);}}CloseServiceHandle(schSCManager);}BOOL SvcStart() { // run service with given nameSC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS); if (schSCManager==0) {long nError = GetLastError();wprintf(L"OpenSCManager failed, error code = %d\n", nError);}else{// open the serviceSC_HANDLE schService = OpenService( schSCManager, SERVICE_NAME, SERVICE_ALL_ACCESS);if (schService==0) {long nError = GetLastError();wprintf(L"OpenService failed, error code = %d\n", nError);}else{// call StartService to run the serviceif(StartService(schService, 0, (LPCWSTR*)NULL)){                wprintf(L"%s started.\n", SERVICE_DISPLAY_NAME);CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return TRUE;}else{long nError = GetLastError();wprintf(L"StartService failed, error code = %d\n", nError);}CloseServiceHandle(schService); }CloseServiceHandle(schSCManager); }return FALSE;}VOID SvcStopNow() {// Open the local default service control manager databaseSC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);if (!schSCManager){wprintf(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError());return;}// Open the service with delete, stop and query status permissionsSC_HANDLE schService = OpenService(schSCManager, SERVICE_NAME, DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS);if (NULL != schService){// Try to stop the serviceSERVICE_STATUS ssSvcStatus;if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus)){wprintf(L"Stopping %s.", SERVICE_DISPLAY_NAME);Sleep(1000);while (QueryServiceStatus(schService, &ssSvcStatus)){if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING){wprintf(L".");Sleep(1000);}else break;}if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED){wprintf(L"\n%s stopped.\n", SERVICE_DISPLAY_NAME);}else{wprintf(L"\n%s failed to stop.\n", SERVICE_DISPLAY_NAME);}}CloseServiceHandle(schService);}else{wprintf(L"OpenService failed w/err 0x%08lx\n", GetLastError());}CloseServiceHandle(schSCManager);}

下面看看運行結果如何。

WIN+R,調出RUN,輸入services.msc調出Service管理。在這裡你就會看見CppWin8Service Demo,點擊一下,會發現其沒有運行。

我們在剛剛install的控制台繼續運行:

D:\honeywell\workspace\Win8Service\Debug>Win8Service.exe -installCppWin8Service Demo installed.D:\honeywell\workspace\Win8Service\Debug>Win8Service.exe -startCppWin8Service Demo started.

重新整理一下Service,會看到此服務以及啟動。

開啟事件檢視器(運行eventvwr.msc),Windows logs---》Application中可以看到CppWin8Service的infomation,比如:

CppWin8ServiceEnter SvcInit

二、外部程式啟動和停止此服務

服務跑起來了,那麼我們如何在外部程式中控制它呢?其實很簡單,就是用上面的SvcStart和SvcStopNow方法來做就可以了。

我們建立一個MFC對話方塊程式,加兩個button,一個啟動一個停止。將兩個函數拷進去,然後包含一下此標頭檔就可以了。

#include <winsvc.h> 

三、批處理安裝服務程式

說白了,就是用sc命令來安裝啟動服務程式,用批處理來封裝一下,注意運行批處理時也要用admin。

sc命令見sc命令建立啟動服務。

Service安裝和啟動的bat:

@echo. start service!@echo off@sc create LincTestServer binPath= "D:\XXX\Debug\NewService.exe"@sc start LincTestServer @sc config LincTestServer start= AUTO@sc config LincTestServer displayname="linc service"@echo off@echo. start ok!@pause


停止的bat:

@echo.stop service@echo off@sc stop LincTestServer @echo off@echo.service stoped@pause


卸載的bat:

@echo.delete service@echo off@sc delete LincTestServer @echo off@echo.service deleted@pause







相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.