svchost服务(DLL服务)
相比于exe服务,DLL服务只需要一个dll,而且运行是通过svchost.exe来运行的,同时安装和卸载的时候需要自己手动修改相关注册表。原理及其细节就不多说了,直接上代码吧(我写的这个是创建新组然后在里面创建新服务的,为了防止刚刚注册的服务因为在别的组里而导致必须下次重启才能启动服务的问题)。
// SvcDll.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include <string>
#include <Strsafe.h>
#include <windows.h>
using namespace std;
#pragma comment(lib,"Advapi32.lib")
#pragma warning(disable:4996)
HMODULE g_hMyself;
DWORD dwCurrState;
SERVICE_STATUS_HANDLE hSrv;
int TellSCM ( DWORD dwState, DWORD dwExitCode, DWORD dwProgress );
void WINAPI ServiceMain ( int argc, wchar_t* argv[] );
void __stdcall ServiceHandler( DWORD dwCommand );
DWORD WINAPI proc_thread(LPVOID lparam);
void Startup()
{
CreateThread(NULL,NULL,proc_thread,NULL,NULL,NULL);
}
void WINAPI ServiceMain( int argc, wchar_t* argv[] )
{
OutputDebugStringA("ServiceMain Load");
TCHAR svcname[256];
wcsncpy(svcname,argv[0] ,256);
hSrv = RegisterServiceCtrlHandler( svcname, (LPHANDLER_FUNCTION)ServiceHandler );
if( hSrv == NULL )
{
OutputDebugStringA("SvcHostDLL RegisterServiceCtrlHandler failed");
return;
}else FreeConsole();
TellSCM( SERVICE_START_PENDING, 0, 1 );
TellSCM( SERVICE_RUNNING, 0, 0 );
Startup();
return;
}
int TellSCM( DWORD dwState, DWORD dwExitCode, DWORD dwProgress )
{
SERVICE_STATUS srvStatus;
srvStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
srvStatus.dwCurrentState = dwCurrState = dwState;
srvStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
srvStatus.dwWin32ExitCode = dwExitCode;
srvStatus.dwServiceSpecificExitCode = 0;
srvStatus.dwCheckPoint = dwProgress;
srvStatus.dwWaitHint = 3000;
return SetServiceStatus( hSrv, &srvStatus );
}
BOOL Is64Sys(){
SYSTEM_INFO si;
GetNativeSystemInfo(&si);
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64
|| si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
return TRUE;
else
return FALSE;
}
BOOL InstallService(const wstring &wsDllFilePath ,const wstring &wsSvcName ,const wstring &wsDescribe){
//Modify registry related
wstring wsSvcGroupName = wstring(wsSvcName) + L"GroupEx";
HKEY hRoot = NULL;
if(ERROR_SUCCESS != RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost",
0,
KEY_QUERY_VALUE | KEY_SET_VALUE,
&hRoot)){
return FALSE;
}
if(ERROR_SUCCESS != RegSetValueEx(
hRoot,
wsSvcGroupName.c_str(),
0,
REG_MULTI_SZ,
(const BYTE *)wsSvcName.c_str(),
(wsSvcName.length() + 1) * sizeof(WCHAR))){
return FALSE;
}
CloseHandle(hRoot);
//install service
SC_HANDLE hscm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hscm == NULL){
return FALSE;
}
wchar_t wszBinPath[MAX_PATH] = { 0 };
if (Is64Sys()){
GetSystemWow64Directory(wszBinPath, MAX_PATH);
StringCchCat(wszBinPath, MAX_PATH, L"\\svchost.exe -k ");
}
else{
GetSystemDirectory(wszBinPath, MAX_PATH);
StringCchCat(wszBinPath, MAX_PATH, L"\\svchost.exe -k ");
}
StringCchCat(wszBinPath, MAX_PATH, wsSvcGroupName.c_str());
SC_HANDLE scHService = CreateService(
hscm, // SCManager database
wsSvcName.c_str(), // name of service
NULL, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_SHARE_PROCESS, // service type
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
wszBinPath, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password
if (scHService == NULL){
return FALSE;
}
//config service
wstring wsRegPath = L"SYSTEM\\CurrentControlSet\\Services\\" + wsSvcName;
if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, wsRegPath.c_str(),
0, KEY_ALL_ACCESS, &hRoot)){
return FALSE;
}
HKEY hSubKey = NULL;
if(ERROR_SUCCESS != RegCreateKey(hRoot, L"Parameters", &hSubKey)){
return FALSE;
}
if(ERROR_SUCCESS != RegSetValueEx(hSubKey, L"ServiceDll", 0, REG_EXPAND_SZ,
(unsigned char*)wsDllFilePath.c_str(), (wsDllFilePath.length() + 1)*sizeof(wchar_t))){
return FALSE;
}
StartService(scHService, 0, NULL);
CloseHandle(hRoot);
CloseHandle(hSubKey);
CloseServiceHandle(scHService);
CloseServiceHandle(hscm);
return TRUE;
}
bool DeleteService(const wstring &wsServiceName) {
HANDLE schSCManager;
SC_HANDLE hService;
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (schSCManager == NULL) return false;
hService=OpenService((struct SC_HANDLE__ *)schSCManager,wsServiceName.c_str(),SERVICE_ALL_ACCESS);
if (hService == NULL) return false;
SERVICE_STATUS status;
QueryServiceStatus(hService, &status); // 获得服务的当前状态
if(::DeleteService(hService)==0) return false;
if(CloseServiceHandle(hService)==0) return false;
return true;
}
bool StopService(const wstring &wsServiceName){
HANDLE schSCManager;
SC_HANDLE hService;
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (schSCManager == NULL) return false;
hService=OpenService((struct SC_HANDLE__ *)schSCManager,wsServiceName.c_str(),SERVICE_ALL_ACCESS);
if (hService == NULL) return false;
SERVICE_STATUS status;
QueryServiceStatus(hService, &status); // 获得服务的当前状态
if (status.dwCurrentState != SERVICE_STOPPED) // 如果服务不处于停止状态,则将其状态设置为
//停止状态
ControlService(hService,SERVICE_CONTROL_STOP, &status);
return true;
}
void __stdcall ServiceHandler( DWORD dwCommand )
{
switch( dwCommand )
{
case SERVICE_CONTROL_STOP:
TellSCM( SERVICE_STOP_PENDING, 0, 1 );
TellSCM( SERVICE_STOPPED, 0, 0 );
break;
case SERVICE_CONTROL_PAUSE:
TellSCM( SERVICE_PAUSE_PENDING, 0, 1 );
TellSCM( SERVICE_PAUSED, 0, 0 );
break;
case SERVICE_CONTROL_CONTINUE:
TellSCM( SERVICE_CONTINUE_PENDING, 0, 1 );
TellSCM( SERVICE_RUNNING, 0, 0 );
break;
case SERVICE_CONTROL_INTERROGATE:
TellSCM( dwCurrState, 0, 0 );
break;
case SERVICE_CONTROL_SHUTDOWN:
TellSCM( SERVICE_STOPPED, 0, 0 );
break;
}
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
g_hMyself = hModule;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
//********************************************************************************
DWORD WINAPI proc_thread(LPVOID lparam)
{
//do something
return 0;
}
wstring wsSvcName = L"Archer";
VOID CALLBACK InsertSvc(){
WCHAR wcDllFilePatu[MAX_PATH] = {0};
GetModuleFileName(g_hMyself, wcDllFilePatu, MAX_PATH);
BOOL bResult = InstallService(wcDllFilePatu ,wsSvcName.c_str() ,wsSvcName.c_str());
}
VOID CALLBACK UninstallSvc(){
StopService(wsSvcName);
DeleteService(wsSvcName);
HKEY hKey;
LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Svchost", 0,KEY_ALL_ACCESS, &hKey);
if(ERROR_SUCCESS == lResult)
{
wstring wsSvcGroupName = wstring(wsSvcName) + L"GroupEx";
RegDeleteValue(hKey ,wsSvcGroupName.c_str());
RegCloseKey(hKey);
}
}
//********************************************************************************
最后记得设置导出函数 def文件,或者是直接把需要导出的函数开始添加相关代码。
我是设置的def文件。DllImport.def内容是
EXPORTS
ServiceMain
InsertSvc
UninstallSvc
写了个测试例子,存在了这个位置,可以直接下载下来编译修改:
http://download.csdn.net/detail/u013761036/9647008
svchost服务(DLL服务)的更多相关文章
- 服务--web服务
.面向对象和面向组件 .什么是Web服务 Web Service "Stack" .Web服务的应用分类 Web服务都是对象/组件技术在Internet中的延伸 面向对象和面向组件 ...
- [转]Windows服务“允许服务与桌面交互”的使用和修改方法
上一篇文章是纯 C# 代码的形式勾上 “允许服务与桌面交互” 选项的 本文转载自:http://blog.csdn.net/lanruoshui/article/details/4756408 描述: ...
- .Net Core微服务系列--服务发现
什么是服务发现 首先我们先思考一个问题,当我们在浏览器中输入一个域名比如baidu.com,然后发生了什么才能让我们访问到百度的网页?简单来说,浏览器会首先从主机的hosts文件中查看是否有baidu ...
- Oracle 11g必须开启的服务及服务详细介绍
转自:http://www.educity.cn/shujuku/404120.html 成功安装Oracle 11g数据库后,你会发现自己电脑运行速度会变慢,配置较低的电脑甚至出现非常卡的状况,通 ...
- 玩转Windows服务系列——服务运行、停止流程浅析
通过研究Windows服务注册卸载的原理,感觉它并没有什么特别复杂的东西,Windows服务正在一步步退去它那神秘的面纱,至于是不是美女,大家可要睁大眼睛看清楚了. 接下来研究一下Windows服务的 ...
- C#操作注册服务卸载服务启动服务停止服务.. .
using Microsoft.Win32; using System; using System.Collections; using System.Collections.Generic; usi ...
- Oracle 11g必须开启的服务及服务详细介绍(转)
成功安装Oracle 11g数据库后,你会发现自己电脑运行速度会变慢,配置较低的电脑甚至出现非常卡的状况,通过禁止非必须开启的Oracle服务可以提升电脑的运行速度.那么,具体该怎么做呢? 按照win ...
- Android(java)学习笔记229:服务(service)之绑定服务调用服务里面的方法 (采用接口隐藏代码内部实现)
1.接口 接口可以隐藏代码内部的细节,只暴露程序员想暴露的方法 2.利用上面的思想优化之前的案例:服务(service)之绑定服务调用服务里面的方法,如下: (1)这里MainActivity.jav ...
- Android(java)学习笔记228:服务(service)之绑定服务调用服务里面的方法
1.绑定服务调用服务里面的方法,图解: 步骤: (1)在Activity代码里面绑定 bindService(),以bind的方式开启服务 : bindServ ...
随机推荐
- List的主要实现类
//ArrayList:List的主要实现类 /* * List中相对于Collection,新增加的方法 * void add(int index, Object ele):在指定的索引位置inde ...
- PTE 准备之 Describe Image
25s 准备时间:决定用什么模板,用模板cover那些信息点 Content: 数字和文字哪个多,就多说哪个,均匀覆盖 Fluency : 保持流利度 不要纠结时态,单复数,人称代词等 时间要求: 尽 ...
- BZOJ_2115 [Wc2011] Xor 【图上线性基】
一.题目 [Wc2011] Xor 二.分析 比较有意思的一题,这里也学到一个结论:$1$到$N$的任意一条路径异或和,可以是一个任意一条$1$到$N$的异或和与图中一些环的异或和组合得到.因为一个数 ...
- python文件处理之fileinput
一.介绍 fileinput模块可以对一个或多个文件中的内容进行迭代.遍历等操作,我们常用的open函数是对一个文件进行读写操作. fileinput模块的input()函数比open函数更高效和好用 ...
- css实现京东顶部导航条
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...
- 【体系结构】Oracle进程架构
Client Process的介绍 Client and Server Processes Client Process代表着客户端进程,每一个客户端进程关联着一个Server Process(服务器 ...
- Android学习之CoordinatorLayout+AppBarLayout
•AppBarLayout 简介 AppbarLayout 是一种支持响应滚动手势的 app bar 布局: 基本使用 新建一个项目,命名为 TestAppBarLayout: 修改 activity ...
- Tkinter系列教程01—引言和安装Tk—Python GUI编程
目录 Tkinter教程系列01--引言和安装Tk 引言 什么是Tkinter 安装 Tk 为 Windows 安装 Tk 验证是否安装正确 为 GNU/Linux 安装 Tk 使用 Linux 的包 ...
- (十六)Struts2的标签库
一.简介 Struts2的标签库使用OGNL为基础,大大简化了数据的输出,也提供了大量标签来生成页面效果,功能非常强大. 在早期的web应用开发中,jsp页面主要使用jsp脚本来控制输出.jsp页面嵌 ...
- 构建一个Flowable命令行应用
官网链接 [(https://flowable.com/open-source/docs/bpmn/ch02-GettingStarted/#building-a-command-line-appli ...