一.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 status
SERVICE_STATUS_HANDLE   g_sshSvcStatusHandle;  // Current service status handle
HANDLE                  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 -install
CppWin8Service Demo installed.D:\honeywell\workspace\Win8Service\Debug>Win8Service.exe -start
CppWin8Service Demo started.

刷新一下Service,会看到此服务以及启动。

打开事件查看器(运行eventvwr.msc),Windows logs---》Application中可以看到CppWin8Service的infomation,比如:

CppWin8Service
Enter 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



Win8上Service程序及外部App调用此Service相关推荐

  1. 调用Web Service实现天气预报

    随时随地技术实战干货,获取项目源码.学习资料,请关注源代码社区公众号(ydmsq666) 一.概念:Web Service用于消除不同平台.不同语言之间的实现差异,将现有的应用程序发布成开放式服务,从 ...

  2. 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(2):处理异步调用中的异常...

    本文来自<ASP.NET AJAX程序设计 第II卷:客户端Microsoft AJAX Library相关>的第三章<异步调用Web Service和页面中的类方法>,请同时 ...

  3. 桌面程序调用Web Service应用实例

    作者:朱金灿 来源:blog.csdn.net/clever101 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com ...

  4. .NET2.0中,Winform程序如何异步调用Web Service呢?[Demo下载]——与.net1.1环境下比较...

    最近在MSDN上看到一个在.NET1.1中Winform程序异步调用WebService的例子 我准备模仿着迁移到.NET2.0环境中,遗憾的是,一切不是那么简单. 首先,.net1.1中调用的Web ...

  5. C#之VS2010ASP.NET页面调用Web Service和winform程序调用Web Service

    一:用ASP.NET调用Web Service 打开VS2010,打开"文件-新建-网站",选择"ASP.NET网站" 选好存储位置,语言后点击确定,进入默认页 ...

  6. .NET应用程序中异步调用Web Service的几种方法 come from: veryhappy(wx.net)

    测试程序界面 图一,调用前界面 图二,调用后界面 详细代码实现 闲言少叙,直接进入主题吧.首先一个声明一个类(将来在客户端与服务器间传递): public class Class1     {     ...

  7. 微信小程序实现微信APP上的扫一扫扫码跳到小程序对应的结果页面和签字等功能

    最近做了一个小程序项目,这个小程序是搭配APP端使用的,大概需求是这样的,用户用微信的扫一扫或小程序首页的扫一扫都可以实现对APP上的二维码进行扫码识别,识别成功之后跳到页面进行渲染,然后用户可以对其 ...

  8. 《ReactNative》app调用小程序的分享

    用ReactNative开发的应用,如果在应用内部,想调用小程序的分享功能,也是可以的. 首先你得有一个正式发布的微信小程序. 1.app和小程序关联 app调用小程序的分享功能,需要在微信开放平台( ...

  9. google app engine上传程序

    上传和管理 Java 应用程序 上传到 Google App Engine Eclipse Google 插件为 Eclipse 工具栏添加了几个按钮.使用"App Engine 部署&qu ...

最新文章

  1. JS滚轮事件(mousewheel/DOMMouseScroll)了解
  2. ZooKeeper伪分布式集群安装及使用
  3. JAVA EXCEL API(jxl)简介
  4. Python之石头剪刀布
  5. Spring 框架蕴含的设计思想
  6. GMapping源码分析之随手笔记
  7. tomcat 设置编码格式
  8. 魔兽世界服务端开服架设服务器搭建教程Centos系统
  9. 由于没有安装音量控制程序,WINDOWS无法在任务栏上显示音量控制,怎么解决?
  10. windows10复制粘贴键突然失效 的一个最简单的解决方法
  11. 主流配置中心的比较 Spring Cloud Config、Apollo、Nacos
  12. 欧框语言框架标准C2,雅思成绩与欧洲语言共同参考框架的对应关系
  13. 机器视觉硬件—相机镜头的选型
  14. 安卓开发-模拟登陆上海理工大学-方正教务系统(HttpsURLConnection)
  15. Android: 渠道号获取
  16. c印记(二):lw_oopc简介
  17. Windows平台监控Android App应用
  18. Swift 2.2 基础语法
  19. 函数图像与MatLab实现(1)
  20. uniapp实现计数器

热门文章

  1. Python分析三季度基金调仓
  2. 免登录 只需要一个QQ号就能获取QQ头像和QQ昵称 获取QQ用户信息API
  3. 计算机网络原理实验(三)——小型校园网络模拟搭建
  4. 国外常用的英文站链接工具
  5. c#实现简单的手写板功能
  6. Python Scrapy 多线程爬取网易云音乐热门歌单信息(手把手教学)
  7. [使用经验] 搜集整理 i9100 含港行,欧水,国行可精简列表完整 12月8日
  8. 什么是自尊心?自尊心对一个人有多重要?优缺点是什么?
  9. 星座时代:一家企业的自白
  10. 漂亮好看的十张思维导图