windows - Service OnExecute mislykkes, spredt tråd udføres ikke

Indlæg af Hanne Mølgaard Plasc

Problem



Først skal du starte med at starte min egen service i Delphi 7. Følg dokumenterne og lavede tjenesten til en tilpasset tråd, der bipper og logger. Kun det gør det ikke. Det sidste forsøg var at lægge samme bip og logkode i OnExecute-hændelsesprocedure, men når jeg starter tjenesten, får jeg en Windows-dialog, der siger, at den blev startet og derefter stoppet igen.


Der bør være noget indlysende, at jeg har overset i denne kode. [4]


Kan du kigge? Jeg accepterer også links til enkle, arbejde, downloadbare serviceeksempler projekter ... bare så får jeg noget, der kaldes hvert 10. sekund eller så, og jeg tager det derfra.

Bedste reference


Se venligst på http://www.delphi3000.com/articles/article\_3379.asp for detaljer om oprettelse af en service. Jeg lavede den post for mange år siden, men skal stadig arbejde. [5]

Andre referencer 1


En tjenestegennemtrængning på knoglerne følger.


Bemærk venligst, at hvis du vil installere tjenesten på Windows Vista og højere ved hjælp af ServiceApp.exe/install, skal du sikre dig, at du kører appen med administratorrettigheder.


Bemærk også, at indholdet af logfilen trods fmShareDenyWrite muligvis ikke kan ses, mens tjenesten kører. I det mindste kunne jeg ikke åbne filen ved hjælp af Notepad ++, før jeg stoppede tjenesten. Dette kan skyldes, at jeg havde tjenesten under systemkontoen (i modsætning til min egen brugerkonto).


En anden bemærkning:
Hvis du vil tillade din tjeneste at blive sat på pause og fortsætter, skal du ikke bruge suspendering og genoptagelse. De er ikke trådsikker og er blevet udskrevet i D2010 +. Brug af T (Simple) Event eller noget lignende at kontrollere hovedarbejderens tråd udførelse.
Hvis du ikke vil tillade din tjeneste at blive standset og fortsætter, kan du blot indstille AllowPause to False.


unit ServiceApp\_fm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs;

type
  TService1 = class(TService)
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
  private
    FWorker: TThread;
  public
    function GetServiceController: TServiceController; override;
  end;

var
  Service1: TService1;

implementation

{$R *.DFM}

type
  TMainWorkThread = class(TThread)
  private
    {$IFDEF UNICODE}
    FLog: TStreamWriter;
    {$ELSE}
    FLog: TFileStream;
    {$ENDIF}
    FRepetition: Cardinal;
  public
    constructor Create;
    destructor Destroy; override;

    procedure Execute; override;
  end;

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  Service1.Controller(CtrlCode);
end;

function TService1.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);
begin
  FWorker := TMainWorkThread.Create;
  Started := True;
end;

procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  // Thread should be freed as well as terminated so we don't have a memory
  // leak. Use FreeAndNil so we can also recognize when the thread isn't
  // available. (When the service has been stopped but the process hasn't ended
  // yet or may not even end when the service is restarted instead of "just" stopped.
  if FWorker <> nil then
  begin
    FWorker.Terminate;
    while WaitForSingleObject(FWorker.Handle, WaitHint-100) = WAIT\_TIMEOUT do
      ReportStatus;
    FreeAndNil(FWorker);
  end;
  Stopped := True;
end;

{ TMainWorkThread }

constructor TMainWorkThread.Create;
var
  FileName: String;
begin
  inherited Create({CreateSuspended=}False);

  FileName := ExtractFilePath(ParamStr(0)) + 'WorkerLog.txt';
  {$IFDEF UNICODE}
  FLog := TStreamWriter.Create(FileName, False, TEncoding.Unicode);
  {$ELSE}
  FLog := TFileStream.Create(FileName, fmCreate);
  {$ENDIF}
end;

destructor TMainWorkThread.Destroy;
begin
  FLog.Free;
  inherited;
end;

procedure TMainWorkThread.Execute;
var
  Text: string;
begin
  inherited;

  while not Terminated do begin
    Inc(FRepetition);
    Text := Format('Logging repetition \%d'#13#10, [FRepetition]);

    {$IFDEF UNICODE}
    FLog.Write(Text);
    {$ELSE}
    FLog.Write(Text[1], Length(Text));
    {$ENDIF}
    Sleep(1000);
  end;
end;

end.

Andre referencer 2


Bipet virker ikke, se dette indlæg.


Din procedure LG er ikke meget robust, det kan mislykkes, hvis logfilen ikke eksisterer. Også brugeren skal have ret til at få adgang til filen. I et første trin kan du køre tjenesten med din brugerkonto for testning.

Andre referencer 3


Fjern under metodebegivenhed


procedure TAviaABSwedenAMailer.ServiceExecute(Sender: TService);
begin
  while not Terminated do
  begin
        Beep;
        Sleep(500);
        LG('Amailer is running');
                ServiceThread.ProcessRequests(False);
  end;
end;