cs_User8
Messages postés30Date d'inscriptionjeudi 24 juillet 2008StatutMembreDernière intervention13 novembre 2012
-
9 nov. 2009 à 12:13
cs_User8
Messages postés30Date d'inscriptionjeudi 24 juillet 2008StatutMembreDernière intervention13 novembre 2012
-
9 nov. 2009 à 17:01
Hello everybody,
Je développe actuellement un bout de code partagé par un exécutable et une dll.
Ce bout de code utilise un TTimer. Avec l'exécutable, tout se passe bien.
Le problème est que dans la dll, l'évènement OnTimer n'est jamais appelé. Aprés quelques recherches, il apparait, sauf erreur de comprehension, que le Timer ait besoin d'etre fenetré. Si il n'est pas fenétré, le message Windows WM_TIMER n'est pas intercepté et l'évènement OnTimer n'est donc jamais exécuté.
Je recherche donc comment utiliser mon bout de code dans ma dll?
Quelqu'un a-t-il déjà rencontré ce problème?
Dois-je créer un forme invisible et l'associer comme parent de mon Timer?
Existe-t-il une autre solution?
cs_User8
Messages postés30Date d'inscriptionjeudi 24 juillet 2008StatutMembreDernière intervention13 novembre 2012 9 nov. 2009 à 17:01
MEA CULPA...
Je viens de résoudre mon problème et il s'avère qu'il n'est pas du tout lié au Timer ... ce bout de code fonctionne très bien! C'est l'appel de la Dll qui était foireux. OnTimer n'avait pas le temps de s'exécuter, la classe contenant le timer était détruite ... Je suis parti dans une mauvaise direction!
cs_User8
Messages postés30Date d'inscriptionjeudi 24 juillet 2008StatutMembreDernière intervention13 novembre 2012 9 nov. 2009 à 13:35
Je tiens quand même à dire qu'avant de poster mon problème j'ai bien entendu effectué divers recherches... J'ai donc également parcouru cette page ... que j'ai également trouvé en moins de 2 minutes.
Ce que je vois sur cette page, c'est le source du TTimer et je ne vois pas trop en quoi cela résout mon problème.
Je vois que le TTimer est censé créer une fenêtre non visuel pour gérer les messages. La question est: pourquoi dans le cas d'une dll, le message WM_TIMER est mal géré? Je pense que mon problème est lié à la gestion des messages WM_TIMER ... mais peut-être je me trompe!
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 9 nov. 2009 à 14:38
Bon alors,
j'ai utilisé la méthode la plus simple ... c'est à dire que je laisse le Timer créer la fenêtre mais on aurait très bien pu utiliser les fonctions SetTimer & KillTimer et créer la fenêtre nous même avec AllocateHwnd afin d'alléger la Dll !!
voilà ... l'exemple est des plus simples il ne fait qu'incrémenter un compteur toutes les secondes ... rien d'autre ... mais on peut tout gérer
DllTimer.zip
[hr]@+Cirec
[hr]
Vous n’avez pas trouvé la réponse que vous recherchez ?
cs_User8
Messages postés30Date d'inscriptionjeudi 24 juillet 2008StatutMembreDernière intervention13 novembre 2012 9 nov. 2009 à 16:45
Je confirme que ta solution marche mais je ne comprends pas pourquoi ca marche dans un cas mais pas dans l'autre ...
voici le bout de code qui coince, c'est une classe qui me permet de lancer des processus:
TProcLauncher = class
private
{ Déclarations privées }
FOutFileName: String;
FOnExit : TProcedure;
FOnTimer : TProcedure;
Timer : TTimer;
ReadPipe,WritePipe : THandle;
Proc_Info : TProcessInformation;
procedure Timer_OnTimer(Sender: TObject);
procedure FreeHandles;
public
{ Déclarations publiques }
Constructor Create;
Destructor Destroy; override;
Function Execute(Cmd : String;
params : String;
title : String;
CheckInterval : Cardinal;
OnTimer : TProcedure;
OnExit : TProcedure;
OutFileName : String): Boolean;
end;
implementation
{ TProcLauncher }
{-----------------------------------------------------------------------
-----------------------------------------------------------------------}
constructor TProcLauncher.Create;
begin
Timer := TTimer.create(nil);
Timer.enabled:=false;
Timer.OnTimer:=Timer_OnTimer;
end;
{-----------------------------------------------------------------------
-----------------------------------------------------------------------}
destructor TProcLauncher.Destroy;
begin
Timer.free;
Inherited Destroy;
end;
{-----------------------------------------------------------------------
Execute une commande
Cmd : La Commande
Params : Les parametres
Title : Le titre
CheckInterval : Interval de temps entre chaque verification d'etat
OnTimer : Evenement sur chaque interval (Nil si inutile)
OnExit : Evenement à la fin de l'execution du process (Nil si inutile)
OutFileName : Redirection en sortie du prcess vers un fichier log ('' si inutile)
-----------------------------------------------------------------------}
Function TProcLauncher.Execute(Cmd, params,title: String; CheckInterval: Cardinal;
OnTimer,OnExit: Tprocedure; OutFileName: String): Boolean;
var
Security : TSecurityAttributes;
startinfo : TStartUpInfo;
begin
result:=false;
if busy then exit; // un process est deja en cours
{Initialisation}
if checkinterval>0 then Timer.Interval:=CheckInterval
else Timer.Interval:=3000;
FoutFilename :=OutFileName;
FOnExit :=OnExit;
FOnTimer :=Ontimer;
With Security do begin
nlength := SizeOf(TSecurityAttributes) ;
binherithandle := true;
lpsecuritydescriptor := nil;
end;
if Createpipe (ReadPipe, WritePipe,@Security, 0) then
begin
FillChar(proc_info, sizeof(TProcessInformation), #0);
FillChar(startinfo, sizeof(TStartupInfo), #0);
startinfo.cb := sizeof(TStartupInfo);
startinfo.hStdOutput := WritePipe;
startinfo.hStdInput := ReadPipe;
startinfo.dwFlags := STARTF_USESTDHANDLES+StartF_USESHOWWINDOW;
startinfo.wShowWindow := SW_HIDE;
startinfo.lpTitle:= PANSICHAR(Title);
if CreateProcess(nil,PANSICHAR(cmd+params),@Security,@Security,
true,CREATE_DEFAULT_ERROR_MODE
+ NORMAL_PRIORITY_CLASS, nil, nil,
startinfo,proc_info) then
Begin
Timer.enabled:=true; //Timer attend la fin de process
result:=true;
End;
End;
if Result=false then FreeHandles;
end;
{-----------------------------------------------------------------------
A chaque top du timer, on met à jour le log et on regarde l'etat du process
-----------------------------------------------------------------------}
procedure TProcLauncher.Timer_OnTimer(Sender: TObject);
var
ExitCode: LongWord;
begin
Timer.Enabled := False;
{Action suivant etat}
if GetExitCodeProcess(proc_info.hProcess, ExitCode) then
Begin
if ExitCode = STILL_ACTIVE
then
begin
if assigned(FOnTimer) then FOntimer;
application.ProcessMessages;
Timer.Enabled := True;
end
else
begin
FreeHandles;
if assigned(FOnExit) then FOnExit;
end;
end
else
begin
FreeHandles;
if assigned(FOnExit) then FOnExit;
end;
end;