Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#8

AW: Unerklärbare Zugriffsverletzung

  Alt 18. Mär 2014, 21:24
Man muß nur den Debugger/IDE mit den nötigen Rechten starten und schon hat man Zugriff.

Zitat:
du könntest ein zweites "Debug"-Projekt erstellen
Ja, es ist recht "einfach" den Service auch als normale Anwendung zu starten.

Meine letzte gewachsene Variante reagiert darauf wie/wo der Service gestartet wurde und verbiegt den Service dann so, daß er als "normale" Anwendung läuft.
Delphi-Quellcode:
uses
  ..., Forms, SvcMgr, ...; // Forms (vor der SvcMgr), damit man Zugriff auf die Messagebehandlung und auf die normale TForm hat.

procedure TMyService.ServiceCreate(Sender: TObject);
var
  Started: Boolean;
  Temp: TForm;
begin
  LogMessage('Service wird erzeugt', EVENTLOG_INFORMATION_TYPE, 0, 1);

  ...

  if IsDebuggerPresent or FindCmdLineSwitch('DEBUG', ['-', '/'], True) then begin
    MyService := Self; // wird sonst von Application.CreateForm gesetzt, aber durch die Messageloop kommt es dort nicht vorbei

    Forms.Application.MainFormOnTaskBar := False; // geht leider doch nicht ohne Form
    Forms.Application.CreateForm(TForm, Temp); // Form zum Beenden und für Eintrag in Taskbar
    Temp.Caption := 'Debug-Mode: ' + SvcMgr.Application.Title;
    Temp.OnCloseQuery := DebugServiceClose;
    Temp.Visible := True;

    // ab hier der Ersatz für SvcMgr.Application.Run, welches sonst sofort Beenden würde, da es kein echter Service ist
    if FindCmdLineSwitch('INSTALL', ['-', '/'], True) then
      TServiceApplicationHack(Application).RegisterServices(True, FindCmdLineSwitch('SILENT', ['-', '/'], True))
    else if FindCmdLineSwitch('UNINSTALL', ['-', '/'], True) then
      TServiceApplicationHack(Application).RegisterServices(False, FindCmdLineSwitch('SILENT', ['-', '/'], True))
    else begin
      Started := True;
      ServiceStart(Self, Started);
      if Started then begin
        ServiceExecute(nil);
        while not Terminated do
          try
            Forms.Application.ProcessMessages;
            Sleep(10);
          except
            on E: Exception do begin
              LogMessage('Error: ' + E.ClassName + ' = ' + E.Message, EVENTLOG_WARNING_TYPE, 0, 22);
              Sleep(1000);
            end;
          end;
      end;
      Forms.Application.Terminate;
    end;
  end;
end;

procedure TMyService.ServiceExecute(Sender: TService);
begin
  LogMessage('Service wird ausgeführt', EVENTLOG_INFORMATION_TYPE, 0, 3);

  ...

  while Assigned(Sender) and not Terminated do//warten auf beenden
    try
      ServiceThread.ProcessRequests(False);
      Sleep(10);
    except
      on E: Exception do begin
        LogMessage('Error: ' + E.ClassName + ' = ' + E.Message, EVENTLOG_WARNING_TYPE, 0, 22);
        Sleep(1000);
      end;
    end;
  LogMessage('Service wurde beendet', EVENTLOG_INFORMATION_TYPE, 0, 5);
end;

procedure TMyService.DebugServiceClose(Sender: TObject; var CanClose: Boolean);
begin
  if Assigned(MyService) and Assigned(MyService.ServiceThread) then
    MyService.ServiceThread.Terminate;
end;
Aber so sind die Rechte natürlich etwas Anderes und auch der "Benutzerkontext", womit da eventuell nicht alle Resourcen gleich verfügbar sind.
Etwas was im Service läuft, könnte hier nicht laufen. Und andersrum.

Zitat:
if Jobs[i].SendWithNextWave = True then
= True ?


Man kann natürlich aud die IDE und den Debugger mit den nötigen Rechten starten.
z.B. als Admin

Oder man lässt den Service in einem anderem Benutzerkontext laufen.
Wenn man den Service im normalen Benutzerkontext laufen lässt, dann hätte er es eventuell auch einfacher auf den Desktop dieses Benutzers zuzugreifen.
$2B or not $2B

Geändert von himitsu (18. Mär 2014 um 21:26 Uhr)
  Mit Zitat antworten Zitat