Win8上Service程序及外部App调用此Service
一.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相关推荐
- 调用Web Service实现天气预报
随时随地技术实战干货,获取项目源码.学习资料,请关注源代码社区公众号(ydmsq666) 一.概念:Web Service用于消除不同平台.不同语言之间的实现差异,将现有的应用程序发布成开放式服务,从 ...
- 使用ASP.NET AJAX异步调用Web Service和页面中的类方法(2):处理异步调用中的异常...
本文来自<ASP.NET AJAX程序设计 第II卷:客户端Microsoft AJAX Library相关>的第三章<异步调用Web Service和页面中的类方法>,请同时 ...
- 桌面程序调用Web Service应用实例
作者:朱金灿 来源:blog.csdn.net/clever101 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com ...
- .NET2.0中,Winform程序如何异步调用Web Service呢?[Demo下载]——与.net1.1环境下比较...
最近在MSDN上看到一个在.NET1.1中Winform程序异步调用WebService的例子 我准备模仿着迁移到.NET2.0环境中,遗憾的是,一切不是那么简单. 首先,.net1.1中调用的Web ...
- C#之VS2010ASP.NET页面调用Web Service和winform程序调用Web Service
一:用ASP.NET调用Web Service 打开VS2010,打开"文件-新建-网站",选择"ASP.NET网站" 选好存储位置,语言后点击确定,进入默认页 ...
- .NET应用程序中异步调用Web Service的几种方法 come from: veryhappy(wx.net)
测试程序界面 图一,调用前界面 图二,调用后界面 详细代码实现 闲言少叙,直接进入主题吧.首先一个声明一个类(将来在客户端与服务器间传递): public class Class1 { ...
- 微信小程序实现微信APP上的扫一扫扫码跳到小程序对应的结果页面和签字等功能
最近做了一个小程序项目,这个小程序是搭配APP端使用的,大概需求是这样的,用户用微信的扫一扫或小程序首页的扫一扫都可以实现对APP上的二维码进行扫码识别,识别成功之后跳到页面进行渲染,然后用户可以对其 ...
- 《ReactNative》app调用小程序的分享
用ReactNative开发的应用,如果在应用内部,想调用小程序的分享功能,也是可以的. 首先你得有一个正式发布的微信小程序. 1.app和小程序关联 app调用小程序的分享功能,需要在微信开放平台( ...
- google app engine上传程序
上传和管理 Java 应用程序 上传到 Google App Engine Eclipse Google 插件为 Eclipse 工具栏添加了几个按钮.使用"App Engine 部署&qu ...
最新文章
- JS滚轮事件(mousewheel/DOMMouseScroll)了解
- ZooKeeper伪分布式集群安装及使用
- JAVA EXCEL API(jxl)简介
- Python之石头剪刀布
- Spring 框架蕴含的设计思想
- GMapping源码分析之随手笔记
- tomcat 设置编码格式
- 魔兽世界服务端开服架设服务器搭建教程Centos系统
- 由于没有安装音量控制程序,WINDOWS无法在任务栏上显示音量控制,怎么解决?
- windows10复制粘贴键突然失效 的一个最简单的解决方法
- 主流配置中心的比较 Spring Cloud Config、Apollo、Nacos
- 欧框语言框架标准C2,雅思成绩与欧洲语言共同参考框架的对应关系
- 机器视觉硬件—相机镜头的选型
- 安卓开发-模拟登陆上海理工大学-方正教务系统(HttpsURLConnection)
- Android: 渠道号获取
- c印记(二):lw_oopc简介
- Windows平台监控Android App应用
- Swift 2.2 基础语法
- 函数图像与MatLab实现(1)
- uniapp实现计数器