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 ...
随机推荐
- 精确率precession和召回率recall
假设有两类样本,A类和B类,我们要衡量分类器分类A的能力. 现在将所有样本输入分类器,分类器从中返回了一堆它认为属于A类的样本. 召回率:分类器认为属于A类的样本里,真正是A类的样本数,占样本集中所有 ...
- Fastjson <=1.2.24-反序列化-任意命令执行
漏洞分析 https://www.secpulse.com/archives/72391.html 复现参考 https://www.cnblogs.com/hack404/p/11980791.ht ...
- 推荐一个能让谷歌浏览器变暗色的插件(darkreader)
下载 https://codechina.csdn.net/mirrors/darkreader/darkreader?utm_source=csdn_github_accelerator 安装教程 ...
- 数据库Redis(一)
Redis数据库的特点: Redis数据库属于nosql数据库的一种,其存储于内存中(非硬盘),修改较为方便. 而Redis数据库的存储方式是使用{key:value}方式存储,类似python基础中 ...
- python学习8 文件的操作
本文拷贝了on testing 的<python之文件操作:文件的读写>,只做学习之用 python的文件读写通过 一.用open函数 二.对文件读写操作 三.读取文件位置定位 1. op ...
- io流(对象流总结)
对象流 对象流就是对引用数据类型进行操作 序列化:将对象的状态信息转换为可以存储或传输的形式的过程,因此类需要序列化后才可以存储到文件中 对象输出流: 很简单,就三句话,将把一个对象导入指定文件中,要 ...
- Centos7下安装JDK详细过程记录
1.查询系统是否安装了java: [root@bogon ~]# java -version 根据上图显示,系统默认安装了Openjdk,它和我们使用的java jdk有些区别(具体的可度娘),所以需 ...
- Logtash 配置文件解析-转载
转载地址:https://dongbo0737.github.io/2017/06/13/logstash-config/ Logtash 配置文件解析 logstash 一个ELK架构中,专门用来进 ...
- Shell prompt(PS1) 与 Carriage Return(CR) 的关系?-- Shell十三问<第二问>
Shell prompt(PS1) 与 Carriage Return(CR) 的关系?-- Shell十三问<第二问> 当你成功登录进一个文字界面之后,大部份情形下,你会在荧幕上看到一个 ...
- QT实现OPC_UA客户端程序以及与OPC_UA服务器通信
1.OPC_UA服务器准备工作 1.关于OPC_UA服务器的搭建可以参考前面一篇文章:https://blog.csdn.net/xipengbozai/article/details/1150809 ...