一个被svchost调用的服务应该做成DLL,所以必须定义DLLMain函数,做为动态库的入口。

DLLMain的代码框架如下:

BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_DETACH:// 将服务状态设置为SERVICE_CONTROL_STOPnotifyServiceManager(SERVICE_CONTROL_STOP, 0, 0);break;default:break;}return TRUE;
}

这里面最重要的是当卸载DLL时,应当通知OS服务已停止,所以需要将服务的状态设置为SERVICE_CONTROL_STOP。本例调用了一个自定义的函数notifyServiceManager来完成服务状态设定,代码如下:

DWORD __currentStatus;int notifyServiceManager(DWORD status, DWORD exitCode, DWORD progress)
{__currentStatus = status;SERVICE_STATUS serviceStatus;serviceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS | SERVICE_INTERACTIVE_PROCESS;serviceStatus.dwCurrentState = status;serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;serviceStatus.dwWin32ExitCode = exitCode;serviceStatus.dwServiceSpecificExitCode = 0;serviceStatus.dwCheckPoint = progress;serviceStatus.dwWaitHint = 0;return SetServiceStatus(__serviceHandle, &serviceStatus);
}

这个函数的最后,调用了Win32 API SetServiceStatus来设置服务状态,关于SetServiceStatus的详细用法,可以参见MSDN文档。

svchost服务DLL应该导出ServiceMain函数,这个函数是服务的入口,代码如下:

SERVICE_STATUS_HANDLE __serviceHandle = nullptr;extern "C" __declspec(dllexport) void ServiceMain(int argc, char *argv[])
{__serviceHandle = RegisterServiceCtrlHandler(argv[0], (LPHANDLER_FUNCTION)ServiceHandler);notifyServiceManager(SERVICE_START_PENDING, 0, 1);notifyServiceManager(SERVICE_RUNNING, 0, 0);HANDLE hThread = CreateThread(nullptr, 0, serviceThread, nullptr, 0, nullptr);if (hThread == nullptr){// writeEventLog("error on create service thread.");}return;
}

注意:ServiceMain函数一定要用extern "C"方式声明,否则,在C++代码中,编译器会为ServiceMain生成一个古怪的名称,因而无法被svchost使用。

上面的代码中创建了一个服务线程,用于执行服务的具体动作。执行代码位域serviceThread函数中,其代码如下:

DWORD WINAPI serviceThread(void *params)
{// 执行具体的服务代码,一般会是循环,需要判断SERVICE_STOP_PENDING和SERVICE_STOPPED状态do {// 执行具体的服务代码} while ((__currentStatus != SERVICE_STOP_PENDING) && (__currentStatus != SERVICE_STOPPED));return 0;
}

ServiceMain注册了服务控制消息响应函数,名为ServiceHandler,代码如下:

void __stdcall ServiceHandler(DWORD dwControl)
{switch (dwControl){case SERVICE_CONTROL_STOP:// do something ...notifyServiceManager(SERVICE_STOP_PENDING, 0, 0);notifyServiceManager(SERVICE_STOPPED, 0, 0);break;case SERVICE_CONTROL_PAUSE:// do something ...notifyServiceManager(SERVICE_PAUSE_PENDING, 0, 1);notifyServiceManager(SERVICE_PAUSED, 0, 0);break;case SERVICE_CONTROL_CONTINUE:// do something ...notifyServiceManager(SERVICE_CONTINUE_PENDING, 0, 1);notifyServiceManager(SERVICE_RUNNING, 0, 0);break;case SERVICE_CONTROL_INTERROGATE:// do something ...notifyServiceManager(__currentStatus, 0, 0);break;default:// do something ...notifyServiceManager(__currentStatus, 0, 0);break;}
}

注意:上面的代码中,对于每一个控制事件,都会对服务的状态做相应的更新。

至此为止,可被svchost调用的服务就制作完成了。

下一篇将说明如何将这个服务注册到svchost中。

制作可被svchost调用的服务(上)相关推荐

  1. IIS上的web service调用AX服务问题

    将web service部署在IIS上后,用windows身份认证调用AX服务,不能访问AX 解决方法:修改应用程序池的标识,改为business connector 账户 转载于:https://w ...

  2. 将应用制作成镜像发布到服务器k8s上作为容器微服务运行。

    全栈工程师开发手册 (作者:栾鹏) 架构系列文章 首先我们需要在本地docker中调试运行一遍,再发布到k8s上去. 如果需要在本地部署k8s环境,可以使用mimnikube,参考:https://b ...

  3. [C#]调用Bartender服务并打印bartender标签

    通常大部分企业在生产,仓储,QC等运作环节会用到标签,标签上有些各种标识. 一般的企业都有配有标签软件+专用的标签打印机.此例以bartender为例子. 如果为了实现打印条码,或者显示具体的功能,用 ...

  4. 【随记】动态调用web服务

    通常我们在程序中需要调用WebService时,都是通过"添加Web引用",让VS.NET环境来为我们生成服务代理,然后调用对应的Web服务.这样是使工作简单了,但是却和提供Web ...

  5. SharePoint 2013 调用WCF服务简单示例

    内容比较简单,主要记录自己使用SharePoint 2013WCF服务遇到的小问题和小经验,分享给大家,希望能够给需要的人有所帮助.好吧,进入正题! 第一部分 SharePoint 2013调用自带W ...

  6. 实现在GET请求下调用WCF服务时传递对象(复合类型)参数

    WCF实现RESETFUL架构很容易,说白了,就是使WCF能够响应HTTP请求并返回所需的资源,如果有人不知道如何实现WCF支持HTTP请求的,可参见我之前的文章<实现jquery.ajax及原 ...

  7. 实现jquery.ajax及原生的XMLHttpRequest调用WCF服务的方法

    废话不多说,直接讲解实现步骤 一.首先我们需定义支持WEB HTTP方法调用的WCF服务契约及实现服务契约类(重点关注各attribute),代码如下: //IAddService.cs namesp ...

  8. Silverlight同步(Synchro“.NET研究”nous)调用WCF服务

    Silverlight的RIA应用中访问远端的WebService或WCF服务,都是通过异步线程模式调用的.在某些情况下我们的调用是需要同步进行,虽然Silverlight没有内置同步线程模式调用远端 ...

  9. Knative 应用在阿里云容器服务上的最佳实践

    作者|元毅 阿里云智能事业群高级开发工程师 相信通过前面几个章节的内容,大家对 Knative 有了初步的体感,那么在云原生时代如何在云上玩转 Knative?本篇内容就给你带来了 Knative 应 ...

  10. asmx 接受 ajax post,jQuery ajax调用web服务(asmx)触发认证弹出框

    在我的asp.net 4.0电子商务web应用程序中,登录的客户可以点击锚点,如"过去6个月内的订单"或"订单去年"来查看他过去的订单.当点击这样的锚,我做一个 ...

最新文章

  1. linux终端拷贝文件内容
  2. 动态毛玻璃特效html,js和CSS3炫酷毛玻璃面板特效
  3. js中函数声明先提升还是变量先提升
  4. vcpkg:使用 vcpkg
  5. Scrapy爬取拉钩网的爬虫(爬取整站CrawlSpider)
  6. 【Vue】使用vue框架制作一个简单的网页
  7. 计算机实验原理word,完整word版计算机组成原理实验报告 微控制器
  8. 【渝粤教育】国家开放大学2019年春季 1292企业集团财务管理 参考试题
  9. Autofac for AutoMapper
  10. 十进制转为二进制的两种方法
  11. Ubuntu 10.04风扇声音太大
  12. 文件下载重命名(跨域)
  13. 直播预告| CVPR专场四来了!
  14. html 与 jsp 文件格式区别
  15. TP5,TP6数据排序方法按指定函数FIELD排序的方法
  16. 高并发下如何设计秒杀系统
  17. 脑机接口应用和P300拼写器概述
  18. 计算机音频服务未运行怎么办,Windows7音频服务未运行怎么办?
  19. 《关于费尔巴哈的提纲》读书笔记
  20. C++ 关于萃取的三种方法

热门文章

  1. iPad——添加学校邮箱到邮件解决方案
  2. Python 字符串 .format 方法详解
  3. 量子计算机中的物理知识,量子计算机和物理学上的量子力学关系大吗?
  4. 40 个科研学术网站,赶紧来收藏一波!
  5. 开启更优网络的时代:Po.et迈入主网
  6. 【开源教程8】疯壳·开源编队无人机-GPIO(LED 航情灯、信号灯控制)
  7. 论文阅读《FSCE: Few-Shot Object Detection via Contrastive Proposal Encoding》
  8. Linux 文件的打包与压缩
  9. Deepin15.3 安装firefox flash插件
  10. Dubbo之手写RPC框架