Delphi Windows服务设计
我之前从未创建过Windows服务,但一直在阅读相关资料。我看到的所有文章或示例都是非常基础的实现和受限制的范围,没有看到任何超越这些或处理特定情况的内容。因此,我已经了解了所有理论知识,并准备深入研究这个项目。我喜欢将我的想法布局出来,并获得人们的反馈意见。我将描述我需要应用程序提供的功能以及我打算如何构建它。我希望得到有经验的Windows服务构建者的评论和任何他们愿意分享的建议。
[场景] 目前我有一个应用程序(我将其称为UPDATEAPPLICATION),它为我们的其他应用程序提供更新。要运行我们的任何应用程序,您必须首先运行此UPDATEAPPLICATION程序并向其传递所需应用程序的参数。UPDATEAPPLICATION调用Web服务,返回XML信息以判断所需应用程序是否有任何更新。
如果有更新,UPDATEAPPLICATION会下载EXE或ZIP格式的更新,并替换相应的文件以更新目标应用程序。之后,UPDATEAPPLICATION执行ShellExecute启动所需应用程序,然后关闭UPDATEAPPLICATION。
这是一个相当基本的过程,多年来一直有效。UPDATEAPPLICATION程序是Delphi应用程序,我们的其他应用程序是混合的:Delphi,VB6,MS Access,.NET。
[问题] 随着转移到Vista和Windows 7,安全性发生了巨大变化。由于UPDATEAPPLICATION的性质,UAC不允许该应用程序在没有管理员权限或关闭UAC的情况下运行。我们正在升级许多应用程序到.NET,在此过程中,我希望应用程序以及UPDATEAPPLICATION符合UAC标准。根据我的研究,唯一的方法是创建UPDATEAPPLICATION作为Windows服务。因此,本质上,我需要将UPDATEAPPLICATION的功能复制到Windows服务架构中。
[我的设计]
我正在使用DelphiXE2。我的设计将包括3个部分,以形成一个完整的解决方案:一个Windows服务、一个小型托盘应用程序来与Windows服务交互,以及我重新设计的应用程序,将向Windows服务发送消息。- 我的Windows服务(我将其称为UPDATESERVICE)将作为Windows服务运行,并创建一个TCP服务器来侦听请求。
- 托盘应用程序(我将其称为TRAYAPP)将使用TCP客户端来配置/管理UPDATESERVICE。
- 当启动我的USERAPPLICATION时,它将向UPDATESERVICE发送一个TCP消息,说明“此应用程序”已经启动。
[UPDATESERVICE] 将侦听消息。如果收到一个消息,说有一个USERAPPLICATION已经启动,将调用Web服务查看是否有更新。如果有更新,用户将被通知关闭应用程序并允许UPDATESERVICE更新应用程序。UPDATESERVICE将下载适当的文件并更新应用程序。
现在我已经解释了我要做的基础知识,我可以问我的具体问题了。这些问题都与如何构建我的Windows服务有关。我还计划使用OmniThread进行线程管理。
当我的服务启动时,我需要创建TCP服务器。
- 应该将TCP服务创建在自己的线程上吗?
- 如果TCP服务是它自己的线程,如何让线程保持活动状态?否则,我可以启动TCP服务,但我不确定在TCP服务单元内应使用什么代码来使线程保持运行状态?
- 哪个Windows Services事件应该创建TCP Service?OnExecute?OnStart?OnCreate?根据我所读的,还不清楚应该使用哪个事件。
- 当TCP Service收到要执行某些操作的消息时,工作应该在TCP Service线程内执行,还是在主UPDATESERVICE中产生一个新的线程?例如:
- 如果TCP Service收到一个使用HTTP检查更新的消息,是否应该在TCP Service线程内产生一个新的线程来执行此操作
- 或者,TCP服务线程是否应向UPDATESERVICE发送消息以生成一个新线程来完成此工作
- 这真的很重要吗?
- 是否可以在Delphi代码中启动/停止/注册/取消注册Windows服务?
这是我的所有问题。可能没有正确/错误的答案,只是基于经验的偏好。如果您使用Delphi构建了服务,则可能有一些对我有用的输入。如果您有一个比基本的“启动服务并睡眠”更强大的项目,并愿意共享它——即使我无法运行或只是伪代码——我相信这将是非常有价值的。谢谢您阅读我冗长的问题。如果您能想出更好的方法,请分享您的想法。我要补充说,我们的几个应用程序可以供公众下载和运行,因此我不能完全控制预期的环境。任何建议/评论/帮助都将不胜感激。
ImagePath
的内容出现在哪里? - NaNImagePath
是由SCM在服务安装时创建的。代码也可以轻松地使用ParamStr(0)
来获取调用进程的路径和文件名。 - Remy Lebeau