windows 服务程序和桌面程序集成(二)服务程序

news2024/9/28 21:27:05

系列文章目录链接:

  1. windows 服务程序和桌面程序集成(一)概念介绍
  2. windows 服务程序和桌面程序集成(二)服务程序
  3. windows 服务程序和桌面程序集成(三)UDP监控工具
  4. windows 服务程序和桌面程序集成(四)桌面程序
  5. windows 服务程序和桌面程序集成(五)集成为一个EXE
  6. windows 服务程序和桌面程序集成(六)集成安装、启动、卸载功能
  7. windows 服务程序和桌面程序集成(七)效果演示及源程序下载

在我的 windows 服务程序和桌面程序集成(一)博文中介绍了Windows 中服务程序桌面程序的基本概念、两种程序的特点。

备注:  

      Windows服务程序桌面程序是两种不同的应用程序类型,它们在运行方式、交互方式和执行环境等方面存在差异。

运行方式:

        桌面程序通常是由用户手动启动的,用户可以通过图形用户界面(GUI)与其交互。而Windows服务程序通常在Windows操作系统启动时就开始运行,并在后台持续运行,通常不需要用户手动启动,也没有GUI。

交互方式:

        桌面程序通常通过GUI与用户进行交互,例如显示窗口、菜单、按钮、文本框等,用户可以使用鼠标、键盘等输入设备与其交互。而Windows服务程序通常不需要用户交互,它们在后台运行,执行特定的任务或提供服务,例如运行网络服务器、备份数据等。

执行环境:

        桌面程序通常在用户交互的环境中运行,例如Windows桌面、移动设备等。而Windows服务程序通常在Windows操作系统的服务控制器中运行,它们以系统级别运行,具有更高的权限和安全性,可以在系统启动时启动,一直运行到系统关闭。

        总的来说,Windows服务程序桌面程序的区别在于它们的运行方式、交互方式和执行环境等方面。Windows服务程序是一种后台程序,通常在Windows操作系统启动时就开始运行,并在后台持续运行,提供特定的服务或执行特定的任务。而桌面程序则是用户手动启动的程序,通常在GUI中显示窗口、菜单、按钮等,用户可以使用鼠标、键盘等输入设备与其交互。

本文详细介绍用Delphi 开发环境创建Windows服务程序桌面程序于一体的双模EXE。也就是说一个EXE文件,既可以表现出Windows服务程序的属性,又可以表现出桌面程序的属性,就是所谓的双模程序。

以下Delphi环境为:Delphi 11.3。如果版本不一样,也基本上是相同的,可能部分界面或者代码稍有不同而已。

一、Delphi环境下Windows服务程序创建、安装、运行步骤

这一节介绍单独的windows服务程序的创建,安装、运行,后面会介绍双模程序的创建:

1. 创建一个 Windows 服务程序:WindowsService_Demo.exe

打开Delphi IDE,选择  File -> New -> Other 

 

 然后选择  Delphi -> Windows  窗口中的 Windos Service 选项,然后 OK 即可!

生成好文件后,保存unit1.pas文件为:uWindows_Service.pas,保存工程文件为:WindowsService_Demo.dproj

 此时可以编译生成为EXE文件,但是这是一个空Service,没有任何功能,就相当于你创建了一个VCL桌面程序,只有一个空白的Form,没有什么实际功能。注意uWindows_Service.pas就相当于VCL桌面程序的主Form。去到源程序目录看,它也包含一个对应的dfm文件 uWindows_Service.dfm。

 对于Windows服务程序,在Delphi  的 IDE中是不能运行的,也不能进行调试运行,按下运行键或者调试键是没有反应的。只能通过工程文件右键菜单中的 Build 命令来生成EXE文件。

 

 至此我们已经成功生成了一个Windows服务程序!

重点:

  1. 所有的windows服务管理接口已经被TService类实现了。在uWindows_Service.pas单元中,我们通过TService1继承了TService,它通过事件和操作系统进行交互。
  2. 通常我们需要一个线程来独立的做我们的实际工作,TService.OnExecute事件不需要做实际的工作。例如我们创建一个uWorkerThread.pas后台线程单元来完成我们的实际工作。
  3. 后台线程(uWorkerThread.pas)随着服务的启动(OnStart事件)而启动,随着服务的停止(OnStop事件)而停止。OnExecute事件等待和处理 ServiceController命令(也就是操作系统的命令)而无需处理我们的实际工作。

一般情况下,我们的OnExecute事件处理代码如下(并没有处理我们的实际任务):

procedure TService1.ServiceExecute(Sender: TService);
begin
  while not Terminated do
  begin
    ServiceThread.ProcessRequests(false);
    TThread.Sleep(1000);
  end;
end;

2. 给 Windows 服务程序:WindowsService_Demo.exe 增加实际工作线程

给Windows服务程序增加一个新单元,名称:uWorkerThread.pas,放在当前工程文件目录的上一级目录中的子目录Public目录下(为什么放在这里?请思考...)。

 工作线程单元uWorkerThread.pas实现的目的是创建一个线程,在线程中每秒通过UDP发送一条消息。由于Windows服务程序是没有界面的,所以通过UDP通信发送一条消息到外边,这样外边的UDP监控程序就可以收到Windows服务程序发送的UDP消息,每秒钟一条消息!

uWorkerThread.pas单元代码:

unit uWorkerThread;

interface
uses
  System.Classes,
  IdUDPClient,
  IdGlobal,
  System.SysUtils;
  //Winapi.Windows;

type
  //实际工作线程类
  TWorkThread = Class(TThread)
     private
       FPaused : Boolean;   //
     protected
       constructor Create;
       procedure Execute; override;
     public
       procedure Pause;
       procedure Continue;
  End;
//服务执行的函数,UDP发送消息函数
procedure Send_UDP_Info(str : string);

var
  //工作线程变量
  WorkThread : TWorkThread;

implementation

procedure Send_UDP_Info(str : string);
var
  UDPClient: TIdUDPClient;
  B : TBytes;
begin
  UDPClient := TIdUDPClient.Create(nil);
  try
    UDPClient.BroadcastEnabled := True;
    B := TEncoding.UTF8.GetBytes(str);
    //只给本机发送,这个地方只需要给本机发送广播消息即可 2023-03-04
    UDPClient.Broadcast(TidBytes(B),8192,'127.0.0.1');  //端口号
    //广播到任何地方
    //UDPClient.Broadcast(TidBytes(B),G_UDPPort);  //端口号
  finally
    UDPClient.Free;
  end;
end;


{ TWorkThread }

procedure TWorkThread.Continue;
begin
  FPaused := False;
  Send_UDP_Info('服务继续工作....');
end;

constructor TWorkThread.Create;
begin
  FPaused := False;
end;

procedure TWorkThread.Execute;
var
  S : string;
begin
  inherited;
  while not Terminated do
  begin
    if not FPaused then
       begin
         S := FormatDateTime('YYYY-MM-DD hh:mm:ss',Now);
         Send_UDP_Info(S);
       end;
    TThread.Sleep(1000);
  end;

  Send_UDP_Info('********** 服务终止工作 **********');
end;

procedure TWorkThread.Pause;
begin
  FPaused := True;
  Send_UDP_Info('服务暂停工作!!!');
end;

end.

3. 给 Windows 服务程序:WindowsService_Demo.exe 修改属性,增加事件代码

  • 修改Windows服务程序的DisplayName属性: AAA,便于在系统服务列表程序中查看。
  •  增加Windows服务程序在系统服务中显示的属性:在ServiceAfterInstall事件中增加如下代码:
procedure TService1.ServiceAfterInstall(Sender: TService);
var
  Reg : TRegistry;
begin
  Reg := TRegistry.Create(KEY_READ or KEY_WRITE);
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    if Reg.OpenKey('SYSTEM\CurrentControlSet\Services\' + Name,False {如果没有就不创建了}) then
      begin
        Reg.WriteString('Description','WindowsService Demo(by SensorWU)') ;
        Reg.CloseKey;
      end;
  finally
    Reg.Free;
  end;
end;

这样在服务程序显示列表中会显示出我们的服务程序的属性信息。

  • 增加Windows服务程序的其他事件代码:

OnStart代码:

procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);
begin
  //创建工作线程
  WorkThread := TWorkThread.Create;
  WorkThread.FreeOnTerminate := True;    //完成后直接释放
end;

OnPause代码:

procedure TService1.ServicePause(Sender: TService; var Paused: Boolean);
begin
  WorkThread.Pause;
  Paused := True;
end;

OnContinue代码:

procedure TService1.ServiceContinue(Sender: TService; var Continued: Boolean);
begin
  WorkThread.Continue;
  Continued := True;
end;

至此,Windows服务程序(独立程序)已经完全写好,通过工程文件右键的Build菜单就可以编译出来服务程序的EXE文件了。其功能是服务程序启动后每隔一秒钟发送一个UDP消息出来,下一节我们需要做一个UDP服务来监测这个消息,这样就能够清晰的看到Windows服务程序的运行,暂停和继续了!

4. Windows服务程序的安装、启动、暂停、继续、卸载

通过上面的步骤,我们已经编译出了Windows服务程序WindowsService_Demo.exe,下面我们来演示Windows服务程序的安装、启动、暂停、继续、卸载。

为了方便(主要是Windows系统不允许网络磁盘上的程序作为Windows服务程序),我们将编译好的WindowsService_Demo.exe拷贝到 C:\Temp目录中。

安装:

通过管理员权限运行CMD,然后进入到C:\Temp目录中

C:\Temp\WindowsService_Demo.exe /install

 安装完成后,在系统的服务列表中就可以看到:

 启动、暂停、继续:

服务启动后就可以出现:停止、暂停、重启动;

服务暂停后就可以出现:停止、恢复、重启动

       

 在服务中可以分别实现 停止、暂停、恢复、重启动

 卸载:

 卸载成功后,在系统的服务列表中将看不到了。

下一篇:windows 服务程序和桌面程序集成(三)UDP监控工具

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/636985.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenLayers.js 入门教程:打造互动地图的入门指南

theme: smartblue 本文简介 戴尬猴,我是德育处主任 本文介绍如何使用 OpenLayers.js (后面简称 ol)。ol 是一个开源 JavaScript 库,可用于在Web页面上创建交互式地图。 ol能帮助我们在浏览器轻松地使用地图功能,例如地图缩放、地图拖动、地图…

双碳目标下DNDC模型建模方法及在土壤碳储量、温室气体排放、农田减排、土地变化、气候变化中的应用

由于全球变暖、大气中温室气体浓度逐年增加等问题的出现,“双碳”行动特别是碳中和已经在世界范围形成广泛影响。国家领导人在多次重要会议上讲到,要把“双碳”纳入经济社会发展和生态文明建设整体布局。同时,提到要把减污降碳协同增效作为促…

数字电子电路绪论

博主介绍:一个爱打游戏的计算机专业学生 博主主页:夏驰和徐策 所属专栏:程序猿之数字电路 1.科技革命促生互联网时代 科技革命对互联网时代的兴起产生了巨大的推动作用。以下是一些科技革命对互联网时代的促进因素: 1. 计算机技…

赢涛智慧工单 v2.4.3 公众号模块版

适用于:入驻加盟、运价查询、申请返礼、工单售后、商标注册、执照申请、汽车保养、年审代办、材料申请、流程审批、贷款申请、废品回收、投诉建议、业务登记、在线督导、购房申请、设备维修、门店报修、信息申请、材料提交、合作咨询、党群服务、入党申请、补贴申领…

内网隧道代理技术(三)之使用SSH端口转发

使用SSH端口转发 SSH介绍 SSH通过网络远程访问主机提供保护,可以对客户端和服务端之间的数据传输进行压缩和加密,有身份验证、SCP、SFTP、和端口转发的功能 SSH转发常用的参数介绍: 参数作用-C请求压缩所有数据-D动态转发、即socks代理-f…

np.meshgrid()与网络表格

目录 数组是如何绘制表格的?分别绘制X和Y图像绘制等高线 数组是如何绘制表格的? 我们先将两个数组传入np.meshgrid(),查看该函数是如何绘制网格的。 import numpy as npx np.linspace(-2, 2, 5) y np.linspace(-2, 2, 5)X, Y np.meshgri…

【无标题】储能电池IEC62619认证 IEC62619测试什么内容

储能电池IEC62619认证 IEC62619测试什么内容 作为专业的民营三方检测、认证服务型的,同时已获得CNAS、CMA、NVLAP、MICOM、A2AL、CPSC、IC、EMSD、NATA、SABS、KOSTEC、 lNSPECCO、E-mark、TUV、CETECOM、EUROFINS、PHOENIX、HOENIX、KTC、ITS、SAA、UL等20多个国内…

在webpack中配置bable

一、什么是bable Babel是一个JavaScript**编译工具**,主要用于在旧浏览器或过时的JavaScript语言版本中转换新的或标准的JavaScript语法和功能。它的主要作用是解决跨浏览器的兼容性问题,让我们能够使用最新的JavaScript特性,而不必担心它们…

一个轻量级Web蜜罐(附下载地址)

Loki 0x01 Why 目标: 抓漏洞. 大概是没有找到啥子开源的符合我预期的蜜罐吧,所以自己动手写了。 0x02 What 想做什么样的蜜罐? 1.便于维护,随开随用,配置简单。 2.Web低仿真即可,且只抓Web流量。 3.不同端口指向不同的页面,响应头配置等。 0x03 How SpringB…

Matlab论文插图绘制模板第102期—分组填充箱线图

在之前的文章中,分享了Matlab箱线图的绘制模板: 填充箱线图的绘制模板: 分组箱线图的绘制模板: 进一步,再来分享一下分组填充箱线图的绘制模板。 先来看一下成品效果: 特别提示:本期内容『数据…

DTMultiWindow UE UMG 多窗口插件说明

本插件可以把UMG窗口做为一个系统窗口独立显示。 目录 操作步骤: DT User Widget 说明: 全局蓝图节点说明 : 操作步骤: 1. 创建一个新的UMG,类型选择 DT User Widget 2. 使用传统方式,搭建这个UMG控件。…

深度学习应用篇-自然语言处理[10]:N-Gram、SimCSE介绍,更多技术:数据增强、智能标注、多分类算法、文本信息抽取、多模态信息抽取、模型压缩算法等

【深度学习入门到进阶】必看系列,含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、序列模型、预训练模型、对抗神经网络等 专栏详细介绍:【深度学习入门到进阶】必看系列,含激活函数、优化策略、损失函数、模型调优、归一化…

redis中的 adlist链表实现

adlist源码解读(基于redis 6.2.7) 1丶打开源码 adlist.h typedef struct listNode {struct listNode *prev;struct listNode *next;void *value; } listNode;//迭代时 使用 typedef struct listIter {listNode *next;int direction; 迭代方向 } listIter;typedef struct lis…

Submit的使用,程序中调用其他报表

Submit的使用 项目需求:编写一个程序能够将实时的物料库存数据通过发送邮件的形式发送到对应的邮件。现有标准的事务码MB5B来查看对应的库存数据。可以在程序中使用submit将参数传递到MB5B中,然后将获取的数据返回到程序中,然后在执行发送邮件…

【Git通关之旅】从山脚到山顶(傲视群雄版)

Git分布式版本控制工具 版本控制器的方式 集中式版本控制工具 集中式版本控制工具,版本库是集中存放在中央服务器的,team里每个人work时从中央服务器下载代 码,是必须联网才能工作,局域网或互联网。个人修改后然后提交到中央版本库…

【蓝桥杯】求既约分数—>(全解)最大公约数与最小公倍数

前言: 通过对【蓝桥杯】2020初赛的一道求既约分数的题目的讲解,引出关于求“最大公约数与最小公倍数”的方法汇总。 对于“最大公约数与最小公倍数”来说,求解都有一些固定的方法,而这些方法一般都是固定的,只需要掌握…

亚马逊、Allegro卖家建立属于自己的测评系统,实现批量优质账号养成

卖家搭建一套完整的测评系统,卖家自己能够养出批量优质账号,并完全掌控真实买家的浏览、加购、下单和评价等风控数据规律。我们的系统能够自主加速推广,防御反击,同时节省运营成本,实现高效的测评运营。 我们的系统支…

传统印刷企业需要部署数字工厂管理系统吗

随着数字化技术的快速发展,传统印刷企业面临着巨大的市场竞争压力。为了提高生产效率,降低生产成本,越来越多的企业开始考虑部署印刷数字工厂管理系统。但是,对于许多企业来说,是否部署印刷数字工厂仍然是一个需要权衡…

【国产复旦微FMQL45教程】-小试牛刀之LED

本教程采用 FMQL7045 FPGA开发板来完成整个试验,板卡照片如下: 具有丰富的接口资源,系统框图如下: 本教程用于完成基于Vivado的FMQL45的LED实验,目标是能够将这款开发板PL端先跑起来。 对于纯 PL 设计,我们…