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 ...
随机推荐
- 七种方案!探讨Redis分布式锁的正确使用姿势
前言 日常开发中,秒杀下单.抢红包等等业务场景,都需要用到分布式锁.而Redis非常适合作为分布式锁使用.本文将分七个方案展开,跟大家探讨Redis分布式锁的正确使用方式.如果有不正确的地方,欢迎大家 ...
- $.ajax data向后台传递参数失败 contentType: "application/json"
在ajax方法设置中若不添加 contentType: "application/json" 则data可以是对象: $.ajax({ url: actionurl, type: ...
- 07、列表list
列表(list) 是一个有序且可变的容器,在里面可以存放多个不同类型的元素 list = ['阿斯顿','阿发师','收发室'] list = [98,88,66,-1] list = [1,True ...
- P2089_烤鸡(JAVA语言)
题目背景 猪猪hanke得到了一只鸡 题目描述 猪猪Hanke特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke吃鸡很特别,为什么特别呢?因为他有10种配料(芥末.孜然等),每种配料可以放1-3克, ...
- 《Selenium自动化测试实战:基于Python》之 Selenium IDE插件的安装与使用
第3章 Selenium IDE插件的安装与使用 京东:https://item.jd.com/13123910.html 当当:http://product.dangdang.com/292045 ...
- Java进阶专题(二十八) Service Mesh初体验
前言 ⽬前,微服务的架构⽅式在企业中得到了极⼤的发展,主要原因是其解决了传统的单体架构中存在的问题.当单体架构拆分成微服务架构就可以⾼枕⽆忧了吗? 显然不是的.微服务架构体系中同样也存在很多的挑战 ...
- Java入门环境的搭建
入门环境搭建 Java帝国的诞生 C & C++ 1972年C诞生 贴近硬件,运行极快,效率极高 操作系统,编译器,数据库,网络系统等 指针和内存管理 1982年C++诞生 面向对象 兼容C ...
- PReact10.5.13源码理解之hook
hook源码其实不多,但是实现的比较精巧:在diff/index.js中会有一些optison.diff这种钩子函数,hook中就用到了这些钩子函数. 在比如options._diff中将curr ...
- 使用 Elastic 技术栈构建 Kubernetes全栈监控
以下我们描述如何使用 Elastic 技术栈来为 Kubernetes 构建监控环境.可观测性的目标是为生产环境提供运维工具来检测服务不可用的情况(比如服务宕机.错误或者响应变慢等),并且保留一些可以 ...
- [状压DP]关灯问题II
关 灯 问 题 I I 关灯问题II 关灯问题II 题目描述 现有n盏灯,以及 m m m个按钮.每个按钮可以同时控制这 n n n盏灯--按下了第 i i i个按钮,对于所有的灯都有一个效果.按下i ...