如何重新启动用Delphi编写的Windows服务应用程序? [英] How can I restart a Windows service application written in Delphi?

查看:167
本文介绍了如何重新启动用Delphi编写的Windows服务应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Delphi编写的Windows服务。偶尔使用的第三方资源之一被破坏,我发现修复这种情况的唯一方法是退出并重新启动程序。我可以检测到程序内部的资源何时被破坏,我可以告诉Windows停止后重新启动服务,但是我无法确定如何让服务告诉自己停止。



程序很简单。我创建了一个似乎是正常方式的服务应用程序。我有一个子类的TService来管理服务,而所有的功能发生在一个单独的线程中。 TService子类几乎只是管理子线程的执行,它在subthread中,我将检测到损坏。



为了参考,这里是标题信息服务和子线程。

 键入
TScannerThread = class(TThread)
private
扫描仪: TScanner;
DefaultDir:String;
ImageDir:String;
程序CheckScanner;
public
父级:TComponent;
程序执行;覆盖
结束

TCardScanSvc = class(TService)
procedure ServiceCreate(Sender:TObject);
procedure ServiceExecute(Sender:TService);
procedure ServiceStart(Sender:TService; var Started:Boolean);
procedure ServiceStop(Sender:TService; var Stopped:Boolean);
procedure ServicePause(Sender:TService; var Paused:Boolean);
procedure ServiceContinue(Sender:TService; var Continued:Boolean);
private
扫描仪线程:TScannerThread;
public
函数GetServiceController:TServiceController;覆盖
结束

var
CardScanSvc:TCardScanSvc;

在GUI应用程序中,我将调用Application.Terminate,但是TServiceApplication似乎没有那个方法。我可以终止subthread,但主线程从来没有注意到,Windows认为该服务仍在运行。我不能真的想到很多其他的尝试。



该程序最初是在Delphi 5中创建的,目前我正在使用Delphi 2007,以防止差异。






编辑:



使用mghie的代码,可以停止服务,但Windows将仅在意外失败时重新启动服务,而不是正常停止。我要做的是做一个单独的服务应用程序,如果有问题,第一个信号是第二个信号,然后重新启动第二个。

解决方案

服务停止是没有问题的 - 我刚刚尝试使用我自己的一个服务,用Delphi 4编写(不使用 TService 类)。以下例程适用于我:

 过程TTestService.StopService; 
var
Scm,Svc:SC_Handle;
状态:SERVICE_STATUS;
begin
Scm:= OpenSCManager(nil,nil,SC_MANAGER_ALL_ACCESS);
如果Scm<> 0然后开始
Svc:= OpenService(Scm,PChar(ServiceName),SERVICE_ALL_ACCESS);
如果Svc 0然后开始
ControlService(Svc,SERVICE_CONTROL_STOP,Status);
// handle Status ....
CloseServiceHandle(Svc);
结束
CloseServiceHandle(Scm);
结束
结束

您需要检查它是否也可以从您的工作线程工作。


I have a Windows service written in Delphi. One of the third-party resources it uses occasionally gets corrupted, and the only way I've found to fix the situation is to exit and restart the program. I can detect when the resource is corrupted from within the program, and I can tell Windows to restart the service after it stops, but I can't figure out how to have the service tell itself to stop.

The program is pretty simple. I created a service application in what seems to be the normal way. I have a subclass of TService to manage the service, while all of the functionality occurs in a separate thread. The TService subclass pretty much just manages the execution of the subthread, and it's in the subthread that I would be detecting the corruption.

For reference, here's the header info for the service and subthread.

type
  TScannerThread = class(TThread)
   private     
    Scanner    : TScanner;
    DefaultDir : String;
    ImageDir   : String;
    procedure CheckScanner;
   public      
    Parent     : TComponent;
    procedure Execute; override;
  end;         

  TCardScanSvc   = class(TService)
    procedure ServiceCreate(Sender: TObject);
    procedure ServiceExecute(Sender: TService);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServicePause(Sender: TService; var Paused: Boolean);
    procedure ServiceContinue(Sender: TService; var Continued: Boolean);
   private        
    ScannerThread : TScannerThread;
   public         
    function GetServiceController: TServiceController; override;
  end;            

var
  CardScanSvc : TCardScanSvc;

In a GUI application, I'd call Application.Terminate, but TServiceApplication doesn't seem to have that method. I can terminate the subthread, but the main thread never notices, and Windows thinks the service is still running. I can't really think of much else to try.

The program was originally created in Delphi 5, and I'm currently using Delphi 2007, in case that makes a difference.


Edit:

With mghie's code, I can stop the service, but Windows will only restart the service if it fails unexpectedly, not if it's stopped normally. What I'm going to do is make a separate service application, have the first signal the second if it has problems, and then have the second restart the first.

解决方案

There is no problem having the service stop itself - I just tried with one of my own services, written with Delphi 4 (without using the TService class). The following routine works for me:

procedure TTestService.StopService;
var
  Scm, Svc: SC_Handle;
  Status: SERVICE_STATUS;
begin
  Scm := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);
  if Scm <> 0 then begin
    Svc := OpenService(Scm, PChar(ServiceName), SERVICE_ALL_ACCESS);
    if Svc <> 0 then begin
      ControlService(Svc, SERVICE_CONTROL_STOP, Status);
      // handle Status....
      CloseServiceHandle(Svc);
    end;
    CloseServiceHandle(Scm);
  end;
end;

You need to check whether it will also work from your worker thread.

这篇关于如何重新启动用Delphi编写的Windows服务应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆