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 endregion

int 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         NULL

VOID 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 endregion

SERVICE_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 service
	g_sshSvcStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME,
		SvcCtrlHandler);
	if (!g_sshSvcStatusHandle)
	{
		SvcReportEvent(L"RegisterServiceCtrlHandler", GetLastError());
		return;
	} 

	// These SERVICE_STATUS members remain as set here
	g_ssSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
	g_ssSvcStatus.dwServiceSpecificExitCode = 0;

	// Report initial status to the SCM
	SvcReportStatus(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 handle
			wType,                 // Event type
			0,                     // Event category
			0,                     // Event identifier
			NULL,                  // No security identifier
			2,                     // Size of lpszStrings array
			0,                     // No binary data
			lpszStrings,           // Array of strings
			NULL);                 // No binary data

		DeregisterEventSource(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 database
	SC_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 CreateService
	SC_HANDLE schService = CreateService(
		schSCManager,                   // SCManager database
		SERVICE_NAME,                   // Name of service
		SERVICE_DISPLAY_NAME,           // Name to display
		SERVICE_CHANGE_CONFIG,          // Desired access
		SERVICE_WIN32_OWN_PROCESS,      // Service type
		SERVICE_DEMAND_START,           // Start type
		SERVICE_ERROR_NORMAL,           // Error control type
		szPath,                         // Service‘s binary
		NULL,                           // No load ordering group
		NULL,                           // No tag identifier
		SERVICE_DEPENDENCIES,           // Dependencies
		SERVICE_ACCOUNT,                // Service running account
		SERVICE_PASSWORD);              // Password of the account

	if (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 database
	SC_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 permissions
	SC_HANDLE schService = OpenService(schSCManager, SERVICE_NAME,
		DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS);

	if (NULL != schService)
	{
		// Try to stop the service
		SERVICE_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 DeleteService
		if (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 database
	SC_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 config
	SC_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 name
	SC_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 service
		SC_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 service
			if(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 database
	SC_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 permissions
	SC_HANDLE schService = OpenService(schSCManager, SERVICE_NAME,
		DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS);

	if (NULL != schService)
	{
		// Try to stop the service
		SERVICE_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

时间: 2024-10-11 03:24:44

Win8上Service程序及外部App调用此Service的相关文章

ios APP 在 waiting for review时重新上传程序

点击details进入后在link点击binary details,进入之后点击右上角reject this binary,然后就可以重新上传了.ios APP 在 waiting for review时重新上传程序

Nginx + FastCGI 程序(C/C++)搭建高性能web service的demo

http://blog.csdn.net/chdhust/article/details/42645313 Nginx + FastCGI 程序(C/C++)搭建高性能web service的Demo 1.介绍 Nginx - 高性能web server,这个不用多说了,大家都知道. FastCGI程序 - 常驻型CGI程序,它是语言无关的.可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能. Nginx要调用FastCGI程序,需要用到FastCGI进程

Java实现与调用Web Service

一. Web Service 1. web service 就是应用程序之间跨语言的调用 例如,天气预报Web Service:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx 2. wsdl: web service description language(web服务描述语言) 通过xml格式说明调用的地址方法如何调用,可以看作webservice的说明书 例如,天气预报的:http://www.webxml.com.cn

C# 调用 Web Service

Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术.是:通过SOAP在Web上提供的软件服务,使用WSDL文件进行说明,并通过UDDI进行注册. XML:(Extensible Markup Language)扩展型可标记语言.面向短期的临时数据处理.面向万维网络,是Soap的基础. Soap:(Simple Object Access Protocol)简单对象存

深入了解以太坊虚拟机第4部分——ABI编码外部方法调用的方式

在本系列的上一篇文章中我们看到了Solidity是如何在EVM存储器中表示复杂数据结构的.但是如果无法交互,数据就是没有意义的.智能合约就是数据和外界的中间体. 在这篇文章中我们将会看到Solidity和EVM可以让外部程序来调用合约的方法并改变它的状态. "外部程序"不限于DApp/JavaScript.任何可以使用HTTP RPC与以太坊节点通信的程序,都可以通过创建一个交易与部署在区块链上的任何合约进行交互. 创建一个交易就像发送一个HTTP请求.Web的服务器会接收你的HTTP

微信小程序引用外部js,引用外部样式,引用公共页面模板

https://blog.csdn.net/smartsmile2012/article/details/83414642 ================小程序引用外部js====================== //封装的函数function GetUserInfo2018() { console.log("获取用户信息8888")} function count(str) { console.log(str)} //转化成小程序模板语言 这一步非常重要 不然无法正确调用mod

VB.NET,C#.NET调用Web Service,利用visual studio 的实现方法

在VB.NET调用Web Service提供的服务 技术qq交流群:JavaDream:251572072 下面是一篇文章比较详细,其实具体操作很简单,把Web Service服务地址,利用工具(VS2010),通过添加引用的形式,添加到项目中来就可以应用了. 大家如果这个地方不会操场的话,可以问问我QQ:1606841559 当Web Service已经处于对外提供服务状态,VB.NET就可以通过HTTP"调用"来使用这些服务了.当然前提是要了解Web Service对外提供服务所对

Web程序员开发App系列 - 开发我的第一个App,源码下载

Web程序员开发App系列 Web程序员开发App系列 - 认识HBuilder Web程序员开发App系列 - 申请苹果开发者账号 Web程序员开发App系列 - 调试Android和iOS手机代码 Web程序员开发App系列 - 开发我的第一个App 待续 目录 前言 源码和App下载 准备工作 查看留言页面 增加留言页面 前言 看了前面几篇文章后我们终于要开始敲代码了,由于所有前端代码都是Html静态问题,所以你用什么开发工具都可以,后台我采用MVC开发,因为Html静态文件需要打包,里面

C# 开发Windows Service程序控制功能

在做一些计划任务时候难免用到Windows Service服务程序,而这个是没有操作界面的,每次启动.重启.关闭都需要服务界面找到服务进行操作,对普通的人来说是非常麻烦的,所以有时候就需要通过应用程序来控制Windows 服务,这里把之前写到的一个服务控制类贴出来. C# Windows 服务控制类代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syste