Autor Beitrag
dannyl2912
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Di 01.07.14 11:26 
Hallo,

ich habe ein Problem, was ich nicht so recht identifiziert bekomme. Bevor ich gleich mit Quelltext-Schnipseln komme eine kurze Erläuterung. Ich möchte einen Dienst erstellen, der einen Zugriff auf die vorhandene MySQL-Datenbank hat, um zukünfigt mit eingehenden Daten automatisiert abarbeiten kann.

Hier die Funktion zum Aufbau der Verbindung. Die übergebene Variable für _SQLConnection ist deklariert und sie funktioniert so in meinem Hauptprogramm, da dies eine geteilt genutzte Unit ist.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
function SQLConnect(_Object: TComponent; dbID: stringvar _SQLConnection: TSQLConnection): boolean;
begin
  _SQLConnection := TSQLConnection.Create(_Object);
  with _SQLConnection do
  begin
    Name := 'SQLConnection' + dbID;
    ConnectionName := 'MySQLConnection';
    // hier evtl. andere Datenbanken prüfen oder über Ini-Datei gehen
    DriverName := 'MySQL';
    GetDriverFunc := 'getSQLDriverMYSQL';
    LibraryName := 'dbexpmysql.dll';
    LoadParamsOnConnect := False;
    LoginPrompt := False;
    KeepConnection := true;
    params.Values['DriverName'] := 'MySQL';
    params.Values['HostName'] := 'localhost'
    params.Values['Database'] := 'db_name';
    params.Values['User_Name'] := 'user';
    params.Values['Password'] := 'pw'
    params.Values['BlobSize'] := '-1';
    params.Values['LocaleCode'] := '0000';
    params.Values['Compress'] := 'True';
    params.Values['Reconnect'] := 'True';
    params.Values['LoginTimeout'] := '60';
    params.Values['ReadTimeout'] := '15';
    params.Values['WriteTimeout'] := '15';
    VendorLib := 'libmysql.dll';
    try
      Connected := true;
    except
     on e:Exception do Protokoll(DateTimeToStr(now)+' ' + e.Message,'service.log');
    end;
  end;
  Result := _SQLConnection.Connected;
end;


In dem Dienst wird dies wie folgend aufgerufen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
procedure TOnlineThread.Execute;
begin

  Protokoll(DateTimeToStr(now)+' Dienst wird gestartet -1 !','service.log');

  if SQLConnect(PZOnline, '1', PSPSQLConnection) = false then // Datenbank-Verbindung aufbauen!
  begin
    Protokoll('Verbindung zum Datenbank-Server nicht möglich!' + #13 + #10 + 'Programm wird beendet!','service.log');
    Terminate;
  end;

  Protokoll(DateTimeToStr(now)+' Dienst wird gestartet -1a !','service.log');


//... weiterer Quellcode

  while not Terminated do
  begin
     Protokoll(DateTimeToStr(now)+' Dienst läuft!','service.log');
     Sleep(500);
  end;

end;


Wenn ich den Teil mit dem SQLConnect auskommentiere kommt mein Dienst in die Schleife und schreibt 'Dienst läuft' in mein Protokoll. Führe ich das notwendige SQLConnect aus, steht der Protokolleintrag mit dem ' Dienst wird gestartet -1 !' als letzter Eintrag. Ich konnte die hängen bleibende Stelle ermitteln. Es ist das Connected=true, selbst ein Open bereitet mir hier ein gleiches Problem. Denn den nachfolgenden Eintrag ' Dienst wird gestartet -1a !' bekomme ich nicht und der Fehlerfall mit einer fehlenden Verbindung bekomme ich ebenso wenig. Im Task-Manager bzw. Dienst-Manager kann ich den Dienst als "laufend" identifizieren. Eine Status-Abfrage am MySQL-Server sagt, dass keine weitere Verbindung aufgebaut wurde.


Danke schon mal

Edit: Quelltext der Funktion um Try-Code erweitert mit gleichem Ergebnis

Moderiert von user profile iconMartok: Code- durch Delphi-Tags ersetzt
Moderiert von user profile iconMartok: Doppelposting entfernt.


Zuletzt bearbeitet von dannyl2912 am Di 01.07.14 14:35, insgesamt 2-mal bearbeitet
baumina
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 305
Erhaltene Danke: 61

Win 7
Delphi 10.2 Tokyo Enterprise
BeitragVerfasst: Di 01.07.14 11:49 
CrossPost .... Antwort siehe forum.delphi-treff.d...ID=441025#post441025
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1321
Erhaltene Danke: 117

Win 10
RIO, CE, Lazarus
BeitragVerfasst: Di 01.07.14 13:02 
Der Login timeout ist auf 60 Sekunden gestellt. Wartest du so lange bis du die Sache als fehlerhaft abbrichst?
Bei deinem Einsatz bisher, da wird die Connection nicht in einem Thread erstellt? Wenn ja, erzeuge die Connection mal außerhalb von Execute.

Ist das ein echter Dienst, oder nur ein eigenständiges Programm das ohne Nutzerinteraktion laufen soll?

Und, nochmal der Hinweis von Baumina (Delphi Treff), es könnte sein das die dll "dbexpmysql.dll" nicht gefunden wird. Verwende mal einen vollständigen Pfad, oder lass dir mal das aktuelle Verzeichnis anzeigen in dem der Dienst gerade steht.

Könnte es sein das der Dienst nicht genügend Rechte bekommt? Schau mal in die System logs ob da was auftaucht.

Hat TSQLConnection ein Event das im Fall von Fehlern ausgelößt wird? Wenn ja implementiere das mal.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
dannyl2912 Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Di 01.07.14 13:16 
Hallo Sinspin,

deine Vermutung ist wie baumina schon vermutete der mySQL-Treiber.

Mit dem Try ... Except-Code konnte ich eine Fehlermeldung erhalten. Auch ein Auslagern aus dem Thread in den aufrufenden Teil (vor Application.Run) brachte nun die gleiche Meldung schon beim Ausführen.


Ja, die Anwendung/Dienst läuft ohne Benutzer-Eingriff eigenständig im Hintergrund, zumindest soll sie das zukünftig.


Einen Pfad zum Treiber angeben werde ich mal versuchen. Es muss nur später berücksichtigt werden, wenn es über diskrete Ini-Dateien beim Kunden geht.



Werde dann mal berichten, wie es nun abläuft. Ich hatte den Nutzer von System auf einem lokalen und Netzwerk-Adminstrator umgesetzt, der alle PATH-Variablen kennen sollte.



Edit:

Wegen dem Timeout von 60 Sekunden, der scheinbar nicht greift. Selbst wenn der Dienst mehrere Minuten in dem Status des Connected=true nicht wollte, kam kein Abbruch über dem Timeout. Vielleicht bin ich von meinen alten dBase-Datenbanken zu sehr verwöhnt.


Ja, es läuft nun. Habe den Pfad zur VendorLib angegeben und seitdem läuft meine Schleife ordnungsgemäß. Ist natürlich schlecht für den Dienst der unter einem Nutzer ausgeführt wird, dem die PATH-Variable bekannt sein sollte.

Vielen Dank dafür.
dannyl2912 Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Di 01.07.14 14:02 
Irgendwie war es das doch nicht, die Meldung bleibt.


Selbst mit Pfadangaben oder in den Programm-Ordner hinterlegte DLLs bringen keine Änderung. Ich wurde dahingehend getäuscht, dass meine Schleife gestartet wurde. Nachdem ich die Absicherung des Verbindungsaufbaus gemacht habe, wird der Dienst korrekt bei fehlender Verbindung (egal was für ein Fehler vorliegt) beendet. Das quittiert mir sogar der Service Manager von Windows korrekt.


Habe die eine DLL in

ausblenden Quelltext
1:
params.Values['LibraryName'] := 'dbxmys.dll';					


umbenannt. Weil die vorherige gar nicht auf meinem System zu finden ist. Nun darf ich mich über eine funktionierende Verbindung meines Hauptprogrammes wundern. Das läuft nach wie vor, egal ob ich "dbexpmysql.dll" drin stehen habe oder "dbxmys.dll", oder die DLLs in ihren Ordnern liegen oder lokal.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 01.07.14 15:10 
Welche Dateien da ggf. gesucht und nicht gefunden werden, kann man mit dem Process Monitor recht einfach sehen.

Dazu kommt, dass das Dienstkonto oft gar keine Netzwerkverbindung aufbauen darf und damit auch keine zu einem SQL Server.
dannyl2912 Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Di 01.07.14 16:01 
Gut, das wäre noch ein Ansatz. Ich gucke mal, was ich heraus bekomme.

Mit dem Server sollten keine Probleme bestehen können. Aktuell wird er lokal ausgeführt. Das wird später beim Kunden auch so sein. Der Dienst hat immer auf dem SQL-Server zu laufen. Das Hauptprogramm ist als Client ausgeführt und muss auf dem Server zugreifen können.

Im Process-Viewer sehe ich, dass er beide genannten DLLs nicht geladen hat, aber auch nicht danach sucht. Ich sehe jedoch, dass er ständig auf die dbxdrivers.ini zugreifen will. Im Vergleich zum Hauptprogramm sieht das ganz anders aus, das lädt diese genutzen DLLs problemlos aus dem gleichen Verzeichnis.

Ich habe dem Dienst einmal die dbxdrivers.ini untergejubelt, aber ohne eine andere Konsequenz.
dannyl2912 Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Mi 02.07.14 09:46 
Mit Hilfe des Process-Viewer bin ich nun so weit, dass ich sagen kann, dass der Dienst nicht mal versucht die libmysql.dll und/oder die dbxmys.dll zu suchen.

Das Hauptprogramm konnte mittels der Pfadvorgaben dazu gebracht werden, die DLLs von anderen Orten zu laden. Dies war schön zu sehen.

Für den Dienst habe ich weitere Manipulationen vorgenommen, Da es auch versucht auf die beiden dbx*.ini zuzugreifen, habe ich ihm auch beide untergeschoben, die Pfad-Angaben enthält. Diese lädt er auch immer brav, auch wenn festgelegt wurde, dass der Dienst diese ignorieren soll. Es ist egal, ob die im gleichen Verzeichnis liegt oder im dbExpress-Ordner, er nimmt die, die er als erstes findet.

Das Ergebnis bleibt wie gehabt, nicht mal der Versuch auf eine der oben genannten DLLs zuzugreifen.