AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Unerklärbare Zugriffsverletzung

Ein Thema von ByTheTime · begonnen am 18. Mär 2014 · letzter Beitrag vom 24. Mär 2014
Antwort Antwort
Seite 1 von 2  1 2   
ByTheTime

Registriert seit: 24. Sep 2011
Ort: Frankfurt
297 Beiträge
 
Delphi XE2 Architect
 
#1

AW: Unerklärbare Zugriffsverletzung

  Alt 18. Mär 2014, 18:15
Erstmal danke für die Antworten

Also es gibt 3 Threads, den ServiceThread, welcher ja immer aktiv ist, jedoch bei mir keine relevanten Aufgaben hat. Dann gibt es noch einen Überwachungs-Thread, welcher auf Events wartet und diese bearbeitet, und den Mail-Thread. Dieser bekommt von dem Überwachungs-Thread immer die Events zugeschoben. Allerdings ist hier alles schön synchronisiert und ich hatte hier noch nie Probleme. Jobs und Events sind je 2 Arrays. Allerdings nicht ineinander verschachtelt. Sie dienen eigentlich nur zum speichern von den Aufträgen und eben den Ergenissen/Events

Die 4 Sekunden enstehen nicht durch das Loggen. Ich habe die besagt Mail-DLL mal aus dem stehgreif runtergetippt. Für jeden Sendevorgang werden die INDY-Komponenten neu initialisiert und einen Verbindung aufgebaut, auch wenn es der gleiche SMTP-Server ist. Klar könnte man das optimieren, aber für meine Zwecke, bei max. 5 Mails in einer Stunde nicht mein primäres Ziel.


@himitsu: Debugmodus Ja hab ich garnicht dran gedacht, aber wie geht das den bei einem Service Meine Vermutung war ja bis jetzt, das die Log Funktion irgendetwas verzögert, allerdings konnte ich das mit Sleep nicht ausgleichen. Wäre schön das nochmal mit dem Debugger durchzugehen.

@Aviator: Jop, der Code wird von einer for-Schleife umgeben. Allerdings hat sich mir kein Sinn ergeben warum hier ein Fehler auftreten könnte. Ich zeige gleich nochmal etwas mehr Code.
Lukas
  Mit Zitat antworten Zitat
ByTheTime

Registriert seit: 24. Sep 2011
Ort: Frankfurt
297 Beiträge
 
Delphi XE2 Architect
 
#2

AW: Unerklärbare Zugriffsverletzung

  Alt 18. Mär 2014, 18:36
Das wäre erstmal die vollständige Schleife von oben:
Delphi-Quellcode:
            for i := 0 to High(Jobs) do // eben für jeden Job durchgehen
            begin
              EventCount := 0; // Event-Zähler zurücksetzen

              if Jobs[i].SendWithNextWave = True then { Eine Vorher gesetzte Variable, welche angibt, ob der Job gesendet wird }
                for j := 0 to High(Events) do
                  if Events[j].AName = Jobs[i].AName then { prüft sozusagen die Zugehörigkeit aller Events zu dem im Moment in Bearbeitung befindlichen Job; Nicht elegant, aber ausreichend }
                    Inc(EventCount);

              if EventCount > 0 then
              begin
                { Log(False, 'EventCount for "' + Jobs[i].Mail + '": ' +
                  IntToStr(EventCount));
                  Log(False, 'All Events: ' + IntToStr(Length(Events))); }


                SendMail(i);
              end;
            end;
Hier wäre dann SendMail:
Delphi-Quellcode:
procedure TMailThread.SendMail(JobID: Integer);
var
  i: Integer;
  MMail: TStringList;
  ID: String;
  // EventCount = (Thread-)Global
begin
  MMail := TStringList.Create;

  MMail.Add('Es wurden ' + IntToStr(EventCount) + ' Meldungen für den Auftrag "'
    + Jobs[JobID].AName + '" gefunden:');
  MMail.Add('');

  { ... }
  { Andere Informationen hinzufügen, die hier aber nicht relevant sind (Keine Schleifen, nur stumpfe Zuweisungen von Text }

  for i := 0 to High(Events) do
    if Events[i].AName = Jobs[JobID].AName then
    begin
      MMail.Add('---');
      MMail.Add(Events[i].Info + ' | ' + Events[i].Time + ' | ' +
        Events[i].Status + ' | ' + Events[i].Date + ' | ' + Events[i].Note);
      MMail.Add('---');
      MMail.Add('');
    end
    else
    begin
      MMail.Add('---');
      MMail.Add(Events[i].Info + ' | ' + Events[i].Time + ' | ' +
        Events[i].Status + ' | ' + Events[i].Date + ' | ' + Events[i].Note);
      MMail.Add('---');
      MMail.Add('');
    end;

  { Der Code hierrüber fügt die Events welche dem passenden Job angehören einfach in den MailText ein. Allerdings frage ich mich gerade selbst, was das mit dem 'else' soll. Habe den Code aus einem anderen Projekt von mir übernommen und etwas umgestellt. Hier ergibt es keinen Sinn, ist mir eben erst aufgefallen, als ich es gepostet habe :D Ich lasse es trotzdem hier mal stehen. }

  MMail.Add('------------------------------------------------------------');
  MMail.Add('');
  MMail.Add('Dieser Bericht wurde um ' + DateTimeToStr(Now) + ' erstellt.');

  MailInfo.AHost := PChar(RPUService.Config.Host);
  MailInfo.APort := StrToInt(RPUService.Config.Port);
  { ... }

  { SMTP- und Mail-Einstellungen }

  ID := SMTPMail.SendMail(MailInfo); // Meine DLL: Zugriff und abschicken

  if ID = 'Successthen // Rückgabewert prüfen und bearbeiten
  begin
    Jobs[JobID].Sended := True;
    Jobs[JobID].SendWithNextWave := False;
    Jobs[JobID].LastTime := TimeOf(Now);
    Log(True, 'INFORMATION: Message to ' + Jobs[JobID].AMail +
      ' was successfully transmitted';
  end
  else
  begin
    Log(True, 'ERROR [' + Jobs[JobID].AMail + ']: ' + ID);
    Jobs[JobID].Sended := False;
    Jobs[JobID].SendWithNextWave := True;
  end;

  MMail.Free;

  if (Length(Events) > 0) and (Jobs[JobID].Sended = True) then
    for i := High(Events) downto 0 do
      if Events[i].AName= Jobs[JobID].AName then
        DeleteEventArrayElement(Events, i);

  { In den 4 Zeilen hierrüber werden die bearbeiteten Events aus der Liste entfernt }
So... Ich hoffe das ist etwas genauer. Ich gehe auch nochmal den Quellcode umgraben.

MfG
Lukas
  Mit Zitat antworten Zitat
Benutzerbild von Ralf Kaiser
Ralf Kaiser

Registriert seit: 21. Mär 2005
Ort: Wuppertal
932 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Unerklärbare Zugriffsverletzung

  Alt 18. Mär 2014, 18:47
@himitsu: Debugmodus Ja hab ich garnicht dran gedacht, aber wie geht das den bei einem Service Meine Vermutung war ja bis jetzt, das die Log Funktion irgendetwas verzögert, allerdings konnte ich das mit Sleep nicht ausgleichen. Wäre schön das nochmal mit dem Debugger durchzugehen.
Hi,

du könntest ein zweites "Debug"-Projekt erstellen, das alle Units aus dem Service enthält und eventuell Logausgaben direkt anzeigt. Dieses Programm läuft dann nicht als Service sondern als normale Applikation die dann einfach mit dem Debugger zu verfolgen ist.

Ciao,
Ralf
Ralf Kaiser
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Unerklärbare Zugriffsverletzung

  Alt 18. Mär 2014, 20: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.
Ein Therapeut entspricht 1024 Gigapeut.

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

Registriert seit: 24. Sep 2011
Ort: Frankfurt
297 Beiträge
 
Delphi XE2 Architect
 
#5

AW: Unerklärbare Zugriffsverletzung

  Alt 18. Mär 2014, 20:36
Ich glaube ich mache ein Debug Projekt, das ist nicht so viel Code, da mach ich mir die "Mühe"

@himitsu:
Zitat:
if Jobs[i].SendWithNextWave = True then
= True ?
Hö?

Was wills du mir damit sagen
Lukas
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Unerklärbare Zugriffsverletzung

  Alt 18. Mär 2014, 21:13
Das Vergleichen mit true ist doppelgemoppel, denn if ... then prüft schon auf not false und dadurch wird das zu if ( Bedingung = true ) <> not false then .

false ist definiert als 0 und true ist das Gegenteil (alles ausser 0). Der Einfachheit halber wurde true (in Delphi) als Konstante mit dem Wert 1 festgelegt. Andere Sprachen verwenden hier andere Werte (z.B. -1 ), was egal ist, wenn man eben nicht mit true vergleicht.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (18. Mär 2014 um 21:21 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.989 Beiträge
 
Delphi 12 Athens
 
#7

AW: Unerklärbare Zugriffsverletzung

  Alt 18. Mär 2014, 21:24
Ich glaube ich mache ein Debug Projekt, das ist nicht so viel Code, da mach ich mir die "Mühe"
Wie schon erwähnt wurde reicht es auch, wenn du Delphi mit Adminrechten startest. Dann kannst du dich einfach mit dem Dienst verbinden...

Wenn es direkt beim Starten passiert, kannst du folgendes nutzen, damit der Dienst wartet bis du den Debugger verbunden hast:
Delphi-Quellcode:
while not IsDebuggerPresent do
  Sleep(100);
Und danach direkt einen Haltepunkt setzen z.B.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
ByTheTime

Registriert seit: 24. Sep 2011
Ort: Frankfurt
297 Beiträge
 
Delphi XE2 Architect
 
#8

AW: Unerklärbare Zugriffsverletzung

  Alt 18. Mär 2014, 21:36
@Sir_Rufo: Okay, habe mir gedacht das er darauf hinauswill. Merke ich mir für die Zukunft...
@jaenicke: Ja stimmt... Habe ich irgendwie dran vorbei gedacht... Und danke für den Tipp mit dem "IsDebuggerPresent"

Noch eine Anmerkung: Eben beim experimentieren ist mir folgendes aufgefallen (man betrachte die for-Schleife welche für das Senden verantwortlich ist):
Delphi-Quellcode:
            for i := 0 to High(Jobs) do
            begin
              { ... }

              if EventCount > 0 then
              begin
                Log(False, 'All Events: ' + IntToStr(Length(Events))); // Geht!

                SendMail(i);
              end;
            end;
Und hier die "andere" Version;

Delphi-Quellcode:
            for i := 0 to High(Jobs) do
            begin
              { ... }

              if EventCount > 0 then
              begin
                Log(False, IntToStr(Length(Events))); // GEHT NICHT!!!

                SendMail(i);
              end;
            end;
Ich debug mich da jetzt durch und dann bin ich mal gespannt, was da genau passiert Denn der Code von oben hat mich nur nochmehr verwirrt
Lukas
  Mit Zitat antworten Zitat
ByTheTime

Registriert seit: 24. Sep 2011
Ort: Frankfurt
297 Beiträge
 
Delphi XE2 Architect
 
#9

AW: Unerklärbare Zugriffsverletzung

  Alt 18. Mär 2014, 22:23
Achso, hier nochmal meine Profi Log-Funktion

Delphi-Quellcode:
procedure Log(ShowDateTime: Boolean; s: String);
var
  LList: TStringList;
  i: Integer;
begin
  FLogCritSect.Enter;

  try
    LList := TStringList.Create;

    if not IsFileInUse(AppDataPath + 'Jobs.jlf') then
    begin
      try
        if FileExists(AppDataPath + 'Log.txt') then
          LList.LoadFromFile(AppDataPath + 'Log.txt');

        for i := 0 to Puffer.Count - 1 do
          LList.Add(Puffer[i]);

        if ShowDateTime then
          LList.Add('[' + DateTimeToStr(Now) + ']: ' + s)
        else
          LList.Add(s);

        LList.SaveToFile(AppDataPath + 'Log.txt');
      finally
        LList.Free;
        Puffer.Text := EmptyStr;
      end;
    end
    else if ShowDateTime then
      Puffer.Add('[' + DateTimeToStr(Now) + ']: ' + s)
    else
      Puffer.Add(s);
  finally
    FLogCritSect.Leave;
  end;
end;
Wenn man in der SendMail-Prozedur eine Zeile hinzufügt funktioniert alles:
Delphi-Quellcode:
{ ... }

Log(False, ''); // Löst alle Probleme

for i := 0 to High(Events) do
  if Events[i].Mail = Jobs[JobID].Mail then
  begin
    { ... }
  end;

{ ... }
Allerdings soll das nicht die Lösung sein... Ich melde mich nochmal!

Gruß
Lukas
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.487 Beiträge
 
Delphi 12 Athens
 
#10

AW: Unerklärbare Zugriffsverletzung

  Alt 19. Mär 2014, 09:25
Also es gibt 3 Threads, den ServiceThread, welcher ja immer aktiv ist, jedoch bei mir keine relevanten Aufgaben hat. Dann gibt es noch einen Überwachungs-Thread, welcher auf Events wartet und diese bearbeitet, und den Mail-Thread. Dieser bekommt von dem Überwachungs-Thread immer die Events zugeschoben. Allerdings ist hier alles schön synchronisiert und ich hatte hier noch nie Probleme. Jobs und Events sind je 2 Arrays. Allerdings nicht ineinander verschachtelt. Sie dienen eigentlich nur zum speichern von den Aufträgen und eben den Ergenissen/Events
Der Überwachungs-Thread fügt neue Elemente dem Array Events hinzu. ("schön sychronisiert" sollte bedeuten, er tut das innerhalb einer Criticalsection.)
Der Mail-Thread liest die Elemente aus Events und löscht diese sogar. ("schön sychronisiert" sollte bedeuten, er tut das ebenfalls innerhalb der selben Criticalsection.)
Ich habe keine einzige Zeile in dieser Hinsicht gesehen.
Hoffentlich bedeuted das, der gesamte Code läuft innerhalb der Criticalsection...
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:05 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz