编写有图形界面的 Windows 服务程序

wsl安装图形界面——体验有脸有面的图形界面 不得不说,自动windows支持linux子系统之后,这又使其成为一大卖点。 首先「Linux」的分发版本非常多,例如有:Ubuntu、openSUSE、SUSE Linux、Fedora、Kali Linux 等等。先拿windows商店中的ubuntu为例。 1.下载ubuntu子系统 2.打开控制面板 → 程序和功能 → 启用或关闭 Windows功能 → 适用于 Linux 的 Windows 子系统,选上后,点击确定,等待安装,然后重启系统。 3.安装完毕后启动 “Ubuntu” 系统,默认是没有 阅读详情

编写有图形界面的 Windows 服务程序

作者:feitian2007

下载源代码

环境:Windows 2003,VC 6.0

摘要:从建立一个COM服务程序入手,然后将一个MFC项目改造成服务程序,最后让这一程序在启动时可以显示图形界面。

关键字:windows服务程序 COM服务程序 开机前启动 NT服务 与桌面交互

一、什么是windows的服务程序?

可以使用下面的几种方法看到它。

  1. 打开控制面板,然后是管理工具,里面有一个“服务”,双击后打开;
  2. 或者是通过输入命令的方式,打开开始菜单,点击运行,输入mmc services.msc(mmc可省略),也可打开;

  我们会在打开的页面中看到一个大的列表,标题栏上包含有名称、描述、状态、启动类型、登录身份等项。其中在状态一栏中显示为“已启动”的是系统中已经启动了的服务。我们先看一下服务的属性。举个例子,找到Print Spooler这一名称,然后用右键在上面点击,选择“属性”,可以看到它所执行的命令行是C:/WINDOWS/system32 /spoolsv.exe,按下停止后,任务管理器中spoolsv.exe进程退出。我们所见到的这个列表就是服务程序的集中地,每一项就是一个服务程序。

上面这些标为自启动的服务程序随系统一起启动。它与一些修改注册表:

HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Run 

项,及类似注册表项的程序不同的是,即使用户没有登录到系统中,它们也是会运行的,或者说它们在系统登录前运行。

二、怎么建立自己的服务程序?

  每一个服务程序对应注册表项HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services下的一个子项。因此我们可以通过增加注册表项的方式增加服务程序。比如,我现在要增加一个test1服务程序,对应的可执行文件是c:/test1.exe。那么我要增加如下注册表项:

  1. [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/]下增加子项test1;
  2. test1下增加:
    字符串型:"Description"="测试服务1"
    字符串型:"DisplayName"="test1-displayname"
    DWORD型:"ErrorControl"=dword:00000001
    可扩充字符串值(即文件所在路径):
    "ImagePath"=hex(2):43,00,3a,00,5c,00,74,00,65,00,73,00,74,00,31,00,2e,00,65,00,/
    78,00,65,00,00,00
    字符串型:"ObjectName"="LocalSystem"
    DWORD型,值为3表示是手动:"Start"=dword:00000003
    DWORD型:"Type"=dword:00000020
  3. test1下增加子项:
    [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/test1/Security]
    里面的键值从其他的服务程序注册表值中复制。

  如果test1这一程序只是一个普通的win32程序,那么这样做了之后还是不行,服务程序有它自己的一些结构特点。那么怎么编写这些服务程序?
  建立一个服务程序的最简单的方法是用VC中的ATL COM向导。主菜单中选择新建,然后选Projects中的ATL COM AppWizard,输入一个项目名,选择了所在目录后,点OK按钮,在出现的对话框中选择Service(EXE),点Finish即可。然后编译生成test1.exe。
  运行test1.exe /regserver可以注册程序为服务,test1.exe /unregserver是取消注册。test1.exe运行时的参数是在:
Project->Settings->Debug->Program arguments中设置。

三、怎么在建立的服务程序中加入自己的代码?

我们看一下刚才生成的test1项目的结构。

  我们看到test1有一个类CServiceModule和一些Globals的内容。Globals包括一个_tWinMain函数,也就是程序的入口,其中使用了FindOneOf这一与分析命令行有关的函数,还剩下一个全局变量_Module。
  _tWinMain函数中,_Module初始化并设置m_bService为TRUE,在一些分析命令行和判断是否为服务的代码之后,使用 _Module.Start()进入主要的执行部分。CServiceModule::Start()中,结构体SERVICE_TABLE_ENTRY 建立了服务名与相应处理函数的映射。在这里,如果m_bService为TRUE,则调用StartServiceCtrlDispatcher进入一种类似win32程序的消息处理的过程,用SERVICE_TABLE_ENTRY中的处理函数让程序执行下去。如果m_bService不为TRUE,则直接执行Run()函数。
  在SERVICE_TABLE_ENTRY中,我们看到服务处理函数为_ServiceMain,继续跟踪下去,发现是ServiceMain函数。在ServiceMain中又调用RegisterServiceCtrlHandler为服务增加了一个_Handler函数。对服务程序来说,我们可以在前面打开的服务列表中对它们进行“启动”,“停止”,“暂停”,“恢复”等操作。这实际上是由_Handler来处理不同的信号。_Handler内部调用Handler,在Handler中,对传入的dwOpcode参数作出处理。比如如果是SERVICE_CONTROL_STOP,也就是我们“ 停止”服务时,将使用PostThreadMessage对主线程发出一个退出的信号。回到ServiceMain函数,在里面同样是在调用Run()函数。也就是说程序以服务身份和非服务身份运行时,区别在于以服务身份运行时多了一个Handler函数,处理用户对服务程序发出的一些信号。
  需要注意的是,这个程序注册为服务时并不是直接写注册表,而是在Install中使用了OpenSCManager,CreateService等函数来完成的任务。显然,这比直接写注册表要好一些,因为有时候我们并不太清楚要怎么去修改注册表项的值来适应不同的服务程序配置,而这些函数有参数可以做到。

说到这里,就涉及到我们自己编写的代码了。
比如现在我们已经建立了一个MFC的程序,想让它成为一个服务程序,那要怎么做呢?
我现在建立一个MFC EXE的项目mfc1,基于对话框。那么把它变为一个服务程序的最简单的方法就是把CServiceModule给拿过来使用。因为我们已经看到CServiceModule类已经把安装服务,卸载服务,运行服务这些操作封装得很好。
打开test1的stdafx.h文件,复制CServiceModule的声明及相关头文件和变量到mfc1的stdafx.h中。
然后是把test1的test1.cpp中对CServiceModule类的实现,复制到mfc1中的mfc1.cpp中。
在stdafx.h中CServiceModule类声明前加上#include <winsvc.h>,它里面是对结构体SERVICE_STATUS_HANDLE的声明。
编译后出现以下类似错误:

D:/vc6_test/mfc1/mfc1.cpp(52) : error C2065: ''IDR_Test1'' : undeclared identifier
D:/vc6_test/mfc1/mfc1.cpp(336) : error C2065: ''CoInitializeSecurity'' : undeclared identifier
D:/vc6_test/mfc1/mfc1.cpp(337) : error C2065: ''EOAC_NONE'' : undeclared identifier
D:/vc6_test/mfc1/mfc1.cpp(362) : error C2065: ''IDS_SERVICENAME'' : undeclared identifier
D:/vc6_test/mfc1/mfc1.cpp(362) : error C2065: ''LIBID_TEST1Lib'' : undeclared identifier

  我们可以在test1中找到IDR_Test1的声明,放到mfc1中,解决第一条错误。但我们也可以去掉CServiceModule中与COM有关的一些代码。这里我们删除RegisterServer,UnregisterServer两个函数,并让Run函数成为

void CServiceModule::Run()
{
    _Module.dwThreadID = GetCurrentThreadId();
    LogEvent(_T("Service started"));
    if (m_bService)
        SetServiceStatus(SERVICE_RUNNING);

    MSG msg;
    while (GetMessage(&msg, 0, 0, 0))
        DispatchMessage(&msg);
}		

增加资源IDS_SERVICENAME为“mfc1”。
注释掉CServiceModule::Init中“CComModule::Init(p, h, plibid);”一行。
注释_tWinMain函数(技巧:用#if 0和#endif注释)。

现在编译程序,应该没有错误了,但加入的CServiceModule还没有起到作用。

在mfc1中的IDD_MFC1_DIALOG上加入两个按钮,分别是“安装服务”,“卸载服务”。增加的单击事件代码为:
“安装服务”按钮:void CMfc1Dlg::OnButton1() { _Module.Install(); }
“卸载服务”按钮:void CMfc1Dlg::OnButton2() { _Module.Uninstall(); }

下面在CMfc1App::InitInstance()中加入一些代码:

_Module.Init(ObjectMap, this->m_hInstance, IDS_SERVICENAME, NULL);
_Module.m_bService = TRUE;
_Module.Start();

  地点是在原来产生对话框的代码的地方。而原有的生成对话框的代码转移到Run()中,位置是在使用了SetServiceStatus函数设置服务状态之后,并注释掉其后的消息处理代码,因对话框自身有消息处理机制。

编译时若出现如下错误,将Install()和Uninstall()前的inline参数去掉即可:

mfc1Dlg.obj : error LNK2001: unresolved external symbol "public: int __thiscall CServiceModule::Install(void)" (?Install@CServiceModule@@QAEHXZ)

mfc1Dlg.obj : error LNK2001: unresolved external symbol "public: int __thiscall CServiceModule::Uninstall(void)" (?Uninstall@CServiceModule@@QAEHXZ)

现在可以编译运行了。然后点击“安装服务”,就可以在服务列表中看到mfc1了。

四、这一服务程序运行时没有图形界面?

  不错,刚才直接运行mfc1.exe时我们看到了图形界面,但在服务列表中用右键菜单中的“启动”时却看不到任何界面。这该怎么办?
我们还需要在使用CreateService函数时(Install()中),加上一个参数,这样才能允许程序与桌面交互,也就是可以显示界面。这个参数是SERVICE_INTERACTIVE_PROCESS。
填加后的CreateService:

    SC_HANDLE hService = ::CreateService(
        hSCM, m_szServiceName, m_szServiceName,
        SERVICE_ALL_ACCESS, 
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
        SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
        szFilePath, NULL, NULL, _T("RPCSS/0"), NULL, NULL);		

再次编译mfc1,卸载服务后,安装服务。我们可以看到,通过服务列表启动mfc1,原有的对话框出现了。

如需将服务设为自动启动,则将 SERVICE_DEMAND_START 改为 SERVICE_AUTO_START。

从STM32F411到华大HC32F460:一个真实项目移植的踩坑与填坑全记录 本文详细记录了从STM32F411移植到华大HC32F460芯片的全过程,包括开发环境搭建、时钟树配置、中断处理、外设驱动、看门狗陷阱、Flash操作和低功耗设计等关键坑点及解决方案。特别针对HC32F460的200MHz主频、双PLL架构和HSRUN模式等特性进行了深入分析,为工程师提供实用的移植指南,帮助节省大量调试时间。 阅读详情

相关推荐

Verilog简易电梯控制系统(2层)

电梯处于1楼,按KEY3,LED3亮,电梯处于上行状态时,立刻按 KEY2,LED2亮,电梯继续运行至2楼,LED3灭;按KEY3,LED3亮,电梯处于上行状态时,立刻按 KEY0,LED0亮,电梯继续运行至2楼,LED3灭;电梯处于2楼,按KEY2,LED2亮,电梯处于下行状态时,立刻按 KEY3,LED3亮,电梯继续运行至1楼,LED2灭;电梯处于2楼,按KEY2,LED2亮,电梯处于下行状态时,立刻按 KEY1,LED1亮,电梯继续运行至1楼,LED2灭;电梯运行至2楼后LED1灭,2楼待机。

m0_54240221的博客 6955

Windows添加自定义服务

【代码】Windows添加自定义服务。

qq_40679799的博客 456

Hive数据迁移

【迁移背景】 本次需要将老集群的hive数据(共30多张表)迁移至新集群中。 老集群版本为CDH5.13,未启用kerberos; 新集群版本为CDH5.14,启用了kerberos。 由于cloudera官方文档说明,在5.x的版本不支持从未启用kerberos的集群与启用了kerberos的集群之间的数据复制。因此无法通过bdr方式进行数据同步。于是采用手工方式进行测试验证。 第一步...

wangkuangood3200的专栏 469

创建自定义的服务Windows NT service

创建自定义的Windows NT service

wsdhla的专栏 5638

Ubuntu 24.04 高效部署Slurm集群:从零到生产环境实战

本文提供了一份在Ubuntu 24.04 LTS系统上从零开始部署生产级Slurm高性能计算集群的完整实战指南。内容涵盖网络配置、Munge安全认证、Slurm核心组件安装与配置,并深入讲解了cgroups资源隔离、NFS共享存储、配置无感知模式等生产环境优化技巧,最后通过实例演示如何提交与管理Slurm作业,帮助用户构建高效、稳定的计算平台。

weixin_29213655的博客 565

VSCode + Latex 配置

1. 安装VSCode VSCode下载 next,next就安装好了。 2. 配置VSCode 2.1 安装LaTeX Workshop插件 install,安装LaTeX Workshop插件 2.2 修改 user setting 点击左下角,进入用户设置 点击上图标记的部分,选择 打开settings.json 具体配置文件如下: { "latex-workshop.la...

一只特立独行的猪 10万+

windows下手动创建服务

windows下手动添加Windows服务

nich_olas的博客 2888

【深度学习】手把手教你在远程服务器上跑 YOLOv3 相关代码(含环境配置)

这篇文章主要记录了如何配置项目环境以及如何在远程服务器上跑 YOLOv3 模型。

作者正在煮茶中... 2384

Windows子系统安装图形界面

Windows子系统安装图形界面 有很多同学需要使用 linux 系统,但是又不想真正安装一个 linux 系统。于是微软大哥就把 ubuntu 系统集成到 windows 内了,你说 微软 屌不屌? 言归正传。 安装xfce4-terminal 因为这个是最靠谱的图形化界面了,所以不解释。 在win10的应用商店中搜索并安装 Xming XServer for Windows,运行其中的 X...

FlyWine的博客 4358

OpenVins解析:基于滤波框架的SLAM

这一方式存在的关键问题是匹配耗时很长,对性能影响显著。可以参考ORBSLAM3中的匹配方式来对其优化,比如左右目匹配可以在极线上搜索,前后帧可以利用运动先验投影匹配。理论上加入路标点会提升精度,代价是增加了计算量。着重说下基于描述子的匹配:OpenVins中匹配的方式是robust_match(),里面是调用的opencv的。openvins中不仅仅进行了传统的MSCKF更新(状态向量中不包含路标点),还在。中进行了包含路标点的估计更新。图像帧到来时,利用IMU递推得到的位姿给该图像帧赋初值。

qq_18076309的博客 4076

DDR5 的 PI: DIMM 上 PMIC,正在制造一批“新型 EMI 问题”

DDR5 的 PI,不再只是“供电设计”,而是一次“噪声管理设计”。电压稳定本地调节高频噪声EMI 风险系统不确定性DDR5 真正难的地方,不是跑起来,而是——在最差条件下,它还能不能一直跑。而 DIMM 上那颗 PMIC,正是你绕不开的关键角色。

weixin_43199439的博客 181

编写有图形界面的 Windows 服务程序(转)

下载源代码环境:Windows 2003,VC 6.0摘要:从建立一个COM服务程序入手,然后将一个MFC项目改造成服务程序,最后让这一程序在启动时可以显示图形界面。关键字:windows服务程序 COM服务程序 开机前启动 NT服务 与桌面交互一、什么是windows的服务程序?可以使用下面的几种方法看到它。1.      打开控制面板,然后是管理工具,里面有

701

【RT-DETR实战】112、NCNN模型转换与层实现支持:从模型文件到推理引擎的硬核实战

本文详细记录了将RT-DETR模型部署到NCNN框架的全过程及关键要点。作者首先遇到MultiHeadAttention等算子不支持的问题,通过ONNX中间转换和自定义层实现解决。文章具体介绍了PyTorch到NCNN的权重转换技巧、模型优化方法(包括量化和线程优化)以及调试经验,强调逐层对比输出、预处理检查和边界情况测试的重要性。最后分享了保持转换流程可复现性的实用建议,指出手动调试虽然耗时但能加深对模型的理解,体现了工程师在解决技术难题时的专业精神与成就感。

企鹅码农的专属播客,分享10多年的实战案例和经验解读,包含YOLO、RT-DETR、AI等各个工作领域。 42

win32服务 mfc 结合 编写有图形界面的 Windows 服务程序

<br /><br />编写有图形界面的 Windows 服务程序<br /><br />作者:feitian2007<br />下载源代码<br />环境:Windows 2003,VC 6.0<br />摘要:从建立一个COM服务程序入手,然后将一个MFC项目改造成服务程序,最后让这一程序在启动时可以显示图形界面。<br />关键字:windows服务程序 COM服务程序 开机前启动 NT服务 与桌面交互<br /><br />一、什么是windows的服务程序?<br />可以使用下面的几种方法看到

ermuzhi的专栏 2763

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

c语言 图形界面 入门,C语言是怎么实现图形界面的?

GTK就可以,一个基于C语言的免费、开源、跨平台图形工具包,可以直接使用C语言调用实现图形界面开发,下面我简单介绍一下这个工具包的安装和使用,这里以Windows平台为例:1.首先,下载GTK安装包,这个可以直接到优快云上下载,一个zip压缩包,直接解压就行,地址https://download.youkuaiyun.com/download/qq_34816564/10925737,解压后的文件如下:2....

weixin_36285392的博客 1万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

VC编写有图形界面的Windows服务程序

环境:Windows 2003,VC 6.0 摘要:从建立一个COM服务程序入手,然后将一个MFC项目改造成服务程序,最后让这一程序在启动时可以显示图形界面。 关键字:windows服务程序 COM服务程序 开机前启动 NT服务 与桌面交互 一、什么是windows的服务程序? 可以使用下面的几种方法看到它。 打开控制面板,然后是管理工具,里面有一个“服务”,双击后打开; 或者是通过输入命令的方式,打开开始菜单,点击运行,输入mmc services.msc(mmc可省略),也可打开; 我们会

懒人的技术笔记 3849

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

devc语言图形编程教程_C语言是怎么实现图形界面的?

GTK就可以,一个基于C语言的免费、开源、跨平台图形工具包,可以直接使用C语言调用实现图形界面开发,下面我简单介绍一下这个工具包的安装和使用,这里以Windows平台为例:1.首先,下载GTK安装包,这个可以直接到优快云上下载,一个zip压缩包,直接解压就行,地址https://download.youkuaiyun.com/download/qq_34816564/10925737,解压后的文件如下:2....

weixin_39662834的博客 5411

windows服务程序一

Windows 服务程序(一) </h1> <div class="clear"></div> <div class="postBody"> <div id="cnblogs_post_body" class="blogpost-body blogpost-body-html"> Wi...

宇之日记 1835

编写有界面的系统服务程序

摘要:从建立一个COM服务程序入手,然后将一个MFC项目改造成服务程序,最后让这一程序在启动时可以显示图形界面。  关键字:windows服务程序 COM服务程序 开机前启动 NT服务 与桌面交互  一、什么是windows的服务程序?  可以使用下面的几种方法看到它。  打开控制面板,然后是管理工具,里面有一个“服务”,双击后打开;  或者是通过输入命令的方式,打开开始菜单,点击运行,输入mmc services.msc(mmc可省略),也可打开;  我们会在打开的页面中看到一个大的列表,标题栏上包含有名

yanglingjay123的专栏 325

Windows下Service服务程序开发

Windows服务程序就是运行在任务管理器中‘服务’选项卡下的程序,可以通过服务控制程序(SCM)进行启动、停止、暂停等操作; SCM程序的打开方式为:单击“开始搜索”框,键入 services.msc,然后按 Enter。截图如下: SCM(service control manager),它是一个系统服务(就是我们上面的截图),我们开发的程序的一生都是通过它控制的,如启动、停止等。 ...

1万+
上一篇: 编写QQ外挂插件的原理和方法
下一篇: 基于MFC对话框的NT服务程序框架
mergerly
博客等级 码龄22年 953粉丝 80原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值