AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Sichtbarkeit von Variablen bei Diensten
Thema durchsuchen
Ansicht
Themen-Optionen

Sichtbarkeit von Variablen bei Diensten

Ein Thema von Caps · begonnen am 6. Apr 2010 · letzter Beitrag vom 6. Apr 2010
Antwort Antwort
Seite 1 von 2  1 2      
Caps

Registriert seit: 23. Mär 2006
Ort: Leipzig
299 Beiträge
 
#1

Sichtbarkeit von Variablen bei Diensten

  Alt 6. Apr 2010, 10:40
Moin,

ich bin dabei, einen Dienst zu programmieren, und habe folgendes Problem:
Im Interface-Teil der Unit habe ich einige Variablen deklariert, die ich im ServiceAfterInstall-Handler des Dienstes aus einer INI-Datei lese. Das geht auch - d.h. die Variablen (global) haben innerhalb der Funktion ServiceAfterInstall die eingelesenen Werte.
Jedoch innerhalb der Funktion Log sind die Werte verschwunden. Da komm ich nicht klar. Keine Ahnung, warum.
Ich benutze showmessage, um die Werte auszugeben.

Die Quelle:

Delphi-Quellcode:
unit Unit1;


interface

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

type
  Tmvideo_sync = class(TService)
    procedure ServiceExecute(Sender: TService);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceAfterUninstall(Sender: TService);
    procedure ServiceBeforeUninstall(Sender: TService);
    procedure ServiceAfterInstall(Sender: TService);
  private
    { Private-Deklarationen }
  public
    function GetServiceController: TServiceController; override;
    { Public-Deklarationen }
  end;


var
   mvideo_sync: Tmvideo_sync;

   videos_dir, // Relativer Pfad
   videos_neu_dir, // Relativer Pfad
   mvideo_sync_homedir : String; // Absoluter Pfad zur Dienst-Executable

   IniFile : TIniFile;
   LogFileName : String; // Ohne Pfadangabe
   IniStringList : TStringList;

   hour_of_execution : Word; // Stunde, zu der das Update durchgeführt werden soll
   UpdateExecuted : Boolean; // Wurde das Update durchgeführt? Dient dazu, einen weiteren Durchlauf während der "Update-Stunde" zu verhindern


implementation

{$R *.DFM}

const
     IniFileName = 'mvideo_sync.ini';


procedure Log(Msg: String);
var
   DTStr : String;
   LogFile : Textfile;
begin showmessage(IntToStr(hour_of_execution) + ', ' + LogFileName + ', ' + videos_dir + ', ' + videos_neu_dir + ', ' + mvideo_sync_homedir); // <------ PROBLEM
  DateTimeToString(DTStr, 'dd.mm.yy hh:mm', now);
  AssignFile(LogFile, mvideo_sync_homedir + '\' + LogFileName);
  Try
     if not FileExists(mvideo_sync_homedir + '\' + LogFileName) then //ReWrite(LogFile)
                                                                else ;//Append(LogFile);
// Try
// WriteLn(LogFile, DTStr + ' : ' + Msg);
// except end;
  finally
// CloseFile(LogFile);
  end;

end;


procedure ExecNewProcess(ProgramName : String); // Mit relativem Pfad aufzurufen
var
   StartInfo : TStartupInfo;
   ProcInfo : TProcessInformation;
   CreateOK : Boolean;
   AbsProgramName : String;
begin
AbsProgramName := mvideo_sync_homedir + '\' + ProgramName;
{ fill with known state }
FillChar(StartInfo, SizeOf(TStartupInfo), #0);
FillChar(ProcInfo, SizeOf(TProcessInformation), #0);
StartInfo.cb := SizeOf(TStartupInfo);

CreateOK := CreateProcess(nil, PChar(AbsProgramName), nil, nil, false, CREATE_NEW_PROCESS_GROUP+NORMAL_PRIORITY_CLASS, nil, nil, StartInfo, ProcInfo);

if CreateOK then
   //may or may not be needed. Usually wait for child processes
   WaitForSingleObject(ProcInfo.hProcess, INFINITE)
            else begin
                 // Log error
                 MessageDlg('Scheiße!', mtError, [mbOK], 0);
                 exit;
                 end;
end;


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


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


procedure Tmvideo_sync.ServiceExecute(Sender: TService);
var
   h, m, s, ms : Word;
begin
while not terminated do begin
      //ServiceThread.ProcessRequests(false);
      DecodeTime(now, h, m, s, ms);
      if h = hour_of_execution + 1 then UpdateExecuted := false; // Indikator rücksetzen, um in ca. 23 Stunden wieder ready zu sein
      if (h = hour_of_execution) and not UpdateExecuted then begin
         Log('Beginning Update...');
         // irgendwas...
         Log('Finished Update');
         UpdateExecuted := true;
                                                             end;
                        end;
end;


procedure Tmvideo_sync.ServiceStart(Sender: TService; var Started: Boolean);
begin
Started := true;
UpdateExecuted := false;

Log('Service started');
end;


procedure Tmvideo_sync.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
Log('Service stopped');
end;

procedure Tmvideo_sync.ServiceAfterUninstall(Sender: TService);
begin
Log('Service has been uninstalled');
end;

procedure Tmvideo_sync.ServiceBeforeUninstall(Sender: TService);
begin
Log('Service is tried to be uninstalled');
end;

procedure Tmvideo_sync.ServiceAfterInstall(Sender: TService);
begin
IniFile := TIniFile.Create(ExtractFilePath(ParamStr(0)) + IniFileName);
IniStringList := TStringList.Create;

IniFile.ReadSectionValues('mvideo_sync', IniStringList);

hour_of_execution := StrToInt(IniStringList.Values ['hour_of_execution']);
LogFileName := IniStringList.Values ['logfile'];
videos_dir := IniStringList.Values ['videos_dir'];
videos_neu_dir := IniStringList.Values ['videos_neu_dir'];
mvideo_sync_homedir := IniStringList.Values ['mvideo_sync_homedir'];

showmessage(IntToStr(hour_of_execution) + ' ' + LogFileName + ' ' + videos_dir + ' ' + videos_neu_dir + ' ' + mvideo_sync_homedir); // <----- KEIN PROBLEM
end;

end.

Für jede Idee dankbar,
Caps
"Der Mode cmCFS8 ist prohibitär und von mir entwickelt."
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: Sichtbarkeit von Variablen bei Diensten

  Alt 6. Apr 2010, 11:39
AfterInstall wird doch nach der Installation aufgerufen, nicht nach dem Start des Services. Dort solltest du die Ini auslesen.
Ich würde auch auf globale Variablen und freie Funktionen verzichten
Markus Kinzler
  Mit Zitat antworten Zitat
Caps

Registriert seit: 23. Mär 2006
Ort: Leipzig
299 Beiträge
 
#3

Re: Sichtbarkeit von Variablen bei Diensten

  Alt 6. Apr 2010, 11:51
Danke für Deine Antwort, aber kannst Du dir trotzdem vorstellen, warum der Wert der Variablen verschwindet?

Edit: ich hatte das Auslesen aus der INI vorher in dem OnStart-Ereignis, es hat auch nicht funktioniert.
Edit2: ich hatte auch eine public-Eigenschaft hinzugefügt, sie im OnInstall-Handler gesetzt, und in der Funktion Log ausgelesen, sie war auch leer.
"Der Mode cmCFS8 ist prohibitär und von mir entwickelt."
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: Sichtbarkeit von Variablen bei Diensten

  Alt 6. Apr 2010, 11:56
Zitat:
Danke für Deine Antwort, aber kannst Du dir trotzdem vorstellen, warum der Wert der Variablen verschwindet?
Diese verschwinden nicht, sondern werden nicht ausgelesen, da diese Methode nur beim Installieren aufgerufen wird. Danach wird der Dienst gestartet ( anderer Prozess), der diese Methode nie ausführt
Markus Kinzler
  Mit Zitat antworten Zitat
Caps

Registriert seit: 23. Mär 2006
Ort: Leipzig
299 Beiträge
 
#5

Re: Sichtbarkeit von Variablen bei Diensten

  Alt 6. Apr 2010, 12:08
Ich dachte es läuft so:

1) Der Dienst wird installiert. Dabei werden den Variablen die entsprechenden Werte zugewiesen.
2) Der Dienst wird gestartet, die Variablen sollten immernoch die Werte haben.
Haben sie aber nicht. Das verstehe ich nicht.


Ich deinstalliere und installiere den Dienst jedesmal neu, wenn ich ihn compiliert habe.
By the way: ich habe die INI-Auslesevorgang jetzt aber im START-Handler, es geht trotzdem nicht. (??? !)


Man betrachte die Variable testi:
- die ist eine public-Eigenschaft des Service-Objectes
- sie wird im START-Ereignis gesetzt und in verschiedenen Methoden (keine freien Funktionen) ausgelesen
showmessage(testi); bringt jedesmal NIX

Delphi-Quellcode:
unit Unit1;


interface

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

type
  Tmvideo_sync = class(TService)
    procedure ServiceExecute(Sender: TService);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceAfterUninstall(Sender: TService);
    procedure ServiceBeforeUninstall(Sender: TService);
    procedure ServiceAfterInstall(Sender: TService);
  private
    { Private-Deklarationen } 
  public
    testi : string;
    function GetServiceController: TServiceController; override;
    { Public-Deklarationen } 
  end;


var
   mvideo_sync: Tmvideo_sync;

   videos_dir, // Relativer Pfad
   videos_neu_dir, // Relativer Pfad
   mvideo_sync_homedir : String; // Absoluter Pfad zur Dienst-Executable

   IniFile : TIniFile;
   LogFileName : String; // Ohne Pfadangabe
   IniStringList : TStringList;

   hour_of_execution : Word; // Stunde, zu der das Update durchgeführt werden soll
   UpdateExecuted : Boolean; // Wurde das Update durchgeführt? Dient dazu, einen weiteren Durchlauf während der "Update-Stunde" zu verhindern


implementation

{$R *.DFM} 

const
     IniFileName = 'mvideo_sync.ini';


procedure Log(Msg: String);
var
   DTStr : String;
   LogFile : Textfile;
begin showmessage(mvideo_sync.testi + IntToStr(hour_of_execution) + ', ' + LogFileName + ', ' + videos_dir + ', ' + videos_neu_dir + ', ' + mvideo_sync_homedir);
  DateTimeToString(DTStr, 'dd.mm.yy hh:mm', now);
  AssignFile(LogFile, mvideo_sync_homedir + '\' + LogFileName);
  Try
     if not FileExists(mvideo_sync_homedir + '\' + LogFileName) then //ReWrite(LogFile)
                                                                else ;//Append(LogFile);
// Try
// WriteLn(LogFile, DTStr + ' : ' + Msg);
// except end;
  finally
// CloseFile(LogFile);
  end;

end;


procedure ExecNewProcess(ProgramName : String); // Mit relativem Pfad aufzurufen
var
   StartInfo : TStartupInfo;
   ProcInfo : TProcessInformation;
   CreateOK : Boolean;
   AbsProgramName : String;
begin
AbsProgramName := mvideo_sync_homedir + '\' + ProgramName;
{ fill with known state } 
FillChar(StartInfo, SizeOf(TStartupInfo), #0);
FillChar(ProcInfo, SizeOf(TProcessInformation), #0);
StartInfo.cb := SizeOf(TStartupInfo);

CreateOK := CreateProcess(nil, PChar(AbsProgramName), nil, nil, false, CREATE_NEW_PROCESS_GROUP+NORMAL_PRIORITY_CLASS, nil, nil, StartInfo, ProcInfo);

if CreateOK then
   //may or may not be needed. Usually wait for child processes
   WaitForSingleObject(ProcInfo.hProcess, INFINITE)
            else begin
                 // Log error
                 MessageDlg('Scheiße!', mtError, [mbOK], 0);
                 exit;
                 end;
end;


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


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


procedure Tmvideo_sync.ServiceExecute(Sender: TService);
var
   h, m, s, ms : Word;
begin
while not terminated do begin
      //ServiceThread.ProcessRequests(false);
      DecodeTime(now, h, m, s, ms);
      if h = hour_of_execution + 1 then UpdateExecuted := false; // Indikator rücksetzen, um in ca. 23 Stunden wieder ready zu sein
      if (h = hour_of_execution) and not UpdateExecuted then begin
         Log('Beginning Update...');
         // irgendwas...
         Log('Finished Update');
         UpdateExecuted := true;
                                                             end;
                        end;
end;


procedure Tmvideo_sync.ServiceStart(Sender: TService; var Started: Boolean);
begin
IniFile := TIniFile.Create(ExtractFilePath(ParamStr(0)) + IniFileName);
IniStringList := TStringList.Create;

IniFile.ReadSectionValues('mvideo_sync', IniStringList);

hour_of_execution := StrToInt(IniStringList.Values ['hour_of_execution']);
LogFileName := IniStringList.Values ['logfile'];
videos_dir := IniStringList.Values ['videos_dir'];
videos_neu_dir := IniStringList.Values ['videos_neu_dir'];
mvideo_sync_homedir := IniStringList.Values ['mvideo_sync_homedir'];

testi := 'gesetzt';

Started := true;
UpdateExecuted := false;

Log('Service started');
end;


procedure Tmvideo_sync.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
showmessage(testi);
Log('Service stopped');
end;

procedure Tmvideo_sync.ServiceAfterUninstall(Sender: TService);
begin
showmessage(testi);
Log('Service has been uninstalled');
end;

procedure Tmvideo_sync.ServiceBeforeUninstall(Sender: TService);
begin
showmessage(testi);
Log('Service is tried to be uninstalled');
end;

procedure Tmvideo_sync.ServiceAfterInstall(Sender: TService);
begin
IniFile := TIniFile.Create(ExtractFilePath(ParamStr(0)) + IniFileName);
IniStringList := TStringList.Create;

IniFile.ReadSectionValues('mvideo_sync', IniStringList);

hour_of_execution := StrToInt(IniStringList.Values ['hour_of_execution']);
LogFileName := IniStringList.Values ['logfile'];
videos_dir := IniStringList.Values ['videos_dir'];
videos_neu_dir := IniStringList.Values ['videos_neu_dir'];
mvideo_sync_homedir := IniStringList.Values ['mvideo_sync_homedir'];

showmessage(testi + IntToStr(hour_of_execution) + ' ' + LogFileName + ' ' + videos_dir + ' ' + videos_neu_dir + ' ' + mvideo_sync_homedir);
end;

end.
"Der Mode cmCFS8 ist prohibitär und von mir entwickelt."
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#6

Re: Sichtbarkeit von Variablen bei Diensten

  Alt 6. Apr 2010, 12:12
Nein. Beim Installieren wird die Exe als normales Programm im Kontext des angemeldeten Benutzers gestartet, welche den Dienst registriert ( Eintragungen in der Registry). Dann wird der Dienst gestartet ( neuer Prozess! unter einem anderen Benutzerkontext!). Der ursprüngliche Prozess wird dann beendet.
Markus Kinzler
  Mit Zitat antworten Zitat
Caps

Registriert seit: 23. Mär 2006
Ort: Leipzig
299 Beiträge
 
#7

Re: Sichtbarkeit von Variablen bei Diensten

  Alt 6. Apr 2010, 12:14
Aber jetzt hab ich's im OnStart-Ereignis. Warum klappt's da auch nicht?
"Der Mode cmCFS8 ist prohibitär und von mir entwickelt."
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#8

Re: Sichtbarkeit von Variablen bei Diensten

  Alt 6. Apr 2010, 12:23
Ich wiederhole mich gerne noch einmal:
Keine gloablen Variablen und freie Funktionen/Prozeduren

Delphi-Quellcode:
Tmvideo_sync = class(TService)
    procedure ServiceExecute(Sender: TService);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceAfterUninstall(Sender: TService);
    procedure ServiceBeforeUninstall(Sender: TService);
    procedure ServiceAfterInstall(Sender: TService);
  private
    { Private-Deklarationen }
  public

   videos_dir, // Relativer Pfad
   videos_neu_dir, // Relativer Pfad
   mvideo_sync_homedir : String; // Absoluter Pfad zur Dienst-Executable

   IniFile : TIniFile;
   LogFileName : String; // Ohne Pfadangabe
   IniStringList : TStringList;

   hour_of_execution : Word; // Stunde, zu der das Update durchgeführt werden soll
   UpdateExecuted : Boolean; // Wurde das Update durchgeführt? Dient dazu, einen weiteren Durchlauf während der "Update-Stunde" zu verhindern
    function GetServiceController: TServiceController; override;
    procedure Log(Msg: String);
    { Public-Deklarationen }
  end;

  ...

procedure Tmvideo_sync.Log(Msg: String);
...
Markus Kinzler
  Mit Zitat antworten Zitat
Caps

Registriert seit: 23. Mär 2006
Ort: Leipzig
299 Beiträge
 
#9

Re: Sichtbarkeit von Variablen bei Diensten

  Alt 6. Apr 2010, 12:30
Ok, ich danke Dir erstmal, ich habe jetzt keine freien Funktionen und keine globalen Variablen mehr (habe mal eine Test-Unit gebaut, nur noch das Gerüst). Es funktioniert dennoch nicht (= showmessage bringt eine leere Box statt des Strings "gesetzt").
Ich bin vielleicht ein bisschen blind oder kapiere irgendeinen Wink nicht, wie gesagt ich hab jetzt (anscheinend) alles, was Du gesagt hast, befolgt (langsam glaub ich an Hexerei )...

Delphi-Quellcode:
unit Unit1;


interface

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

type
  Tmvideo_sync = class(TService)
    procedure ServiceExecute(Sender: TService);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceAfterUninstall(Sender: TService);
    procedure ServiceBeforeUninstall(Sender: TService);
    procedure ServiceAfterInstall(Sender: TService);
  private
    { Private-Deklarationen } 
  public
    testi : string;
    function GetServiceController: TServiceController; override;
    { Public-Deklarationen } 
  end;


var
   mvideo_sync: Tmvideo_sync;


implementation

{$R *.DFM} 


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


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


procedure Tmvideo_sync.ServiceExecute(Sender: TService);
var
   h, m, s, ms : Word;
begin
while not terminated do begin
      //ServiceThread.ProcessRequests(false);
                        end;
end;


procedure Tmvideo_sync.ServiceStart(Sender: TService; var Started: Boolean);
begin
testi := 'gesetzt';
Started := true;
end;


procedure Tmvideo_sync.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
showmessage(testi);
end;

procedure Tmvideo_sync.ServiceAfterUninstall(Sender: TService);
begin
showmessage(testi);
end;

procedure Tmvideo_sync.ServiceBeforeUninstall(Sender: TService);
begin
showmessage(testi);
end;

procedure Tmvideo_sync.ServiceAfterInstall(Sender: TService);
begin
showmessage(testi);
end;

end.
"Der Mode cmCFS8 ist prohibitär und von mir entwickelt."
  Mit Zitat antworten Zitat
Caps

Registriert seit: 23. Mär 2006
Ort: Leipzig
299 Beiträge
 
#10

Re: Sichtbarkeit von Variablen bei Diensten

  Alt 6. Apr 2010, 12:36
Ok, innerhalb von ServiceExecute wird der Wert ausgelesen.
Ich mache also alles zu Eigenschaften und Methoden des Service-Objektes. Dann müsste es klappen, oder? Alles, was nach ServiceStart und vor ServiceStop passiert, kann "miteinander reden"...?

Wie die globalen Variablen allerdings gehandhabt werden bzw. wie ich mir das vorstellen soll, verstehe ich allerdings immernoch nicht so richtig...

Caps
"Der Mode cmCFS8 ist prohibitär und von mir entwickelt."
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 18:25 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz