7
votes

Redémarrez Delphi Application Programmatiquement

Il ne devrait pas être possible d'exécuter plusieurs instances de mon application. Par conséquent, la source de projet contient: xxx

maintenant, je veux redémarrer ma demande par programme. La voie habituelle serait: xxx

mais cela ne fonctionnera pas dans mon cas à cause du mutex. Même si je libère le mutex avant de commencer le deuxième instacle, il ne fonctionnera pas car l'arrêt prend du temps et deux instance ne peuvent pas fonctionner en parallèle (en raison de ressources communes et d'autres effets).

est là un moyen de Redémarrez une application avec de telles caractéristiques? (Si possible sans un exécutable supplémentaire)

Merci d'avance.


4 commentaires

Pourquoi recommencer - activez simplement l'instance déjà en cours d'exécution


Comment est-ce la même chose? L'instance de fonctionnement est déjà active et je veux que cela soit redémarré.


Avez-vous déjà testé le retour de 'Releasemutex'?


libérer n'est pas ce que vous devez faire au mutex. Fermez-le à la place.


9 Réponses :


0
votes

Vous pouvez passer un argument de ligne de commande comme "redémarrer" et exécuter un sommeil () avant d'essayer d'acquérir le mutex ou d'essayer d'acquérir le mutex dans une boucle qui dort un moment.

Aussi, vous pouvez configurer une communication entre les deux processus, mais cela pourrait être surchargé.


1 commentaires

Le problème avec le dormir est qu'il n'ya aucun moyen de trouver une valeur appropriée. Dépend totalement de l'ordinateur, des données chargées et d'autres choses.



1
votes

Incluez dans votre shellexecute Quelque paramètre, par exemple, / waitforshutdown et créez un plus mutex. Dans votre programme, avant l'initialisation, par exemple dans son fichier .DPR, insérez quelque chose comme:

Si (POS ('/ WaitForShutdown', CMDLINE) <> 0) alors WaitforsingleObject (shutdownmutexhandle, infini);

Aussi, dans votre programme, après toutes les finalisations et libérant vos ressources communes, incluez quelque chose comme

releasemutex (shutdownmutexhandle);


2 commentaires

Merci! Mais shutdownMutexhandle sera indéfini au début du programme. Comment le définiriez-vous? Createmutex échouera avec error_already_exists erreur ...


ok je suppose que je l'ai trouvé: openmutex devrait être la bonne chose à appeler pour obtenir la poignée.



0
votes

Salut Jetez un coup d'œil à un look A l'article suivant Par Zarko Gajic - Là, vous obtiendrez des idées, un échantillon de code et même un composant entier à utiliser.

hth, Reinhard


1 commentaires

Je crois que c'est plus pertinent - delphi.about.com/cs/adpts2001/a /bltip0601_2.htm



2
votes

Pourquoi ne pouvez-vous pas simplement libérer le mutex avant de tenter de redémarrer? Si, par une occasion, un autre instance devient avant que celui que vous invoquez explicitement avec le redémarrage qui n'a pas d'importance, vous aurez toujours votre application et courez à nouveau avec les modifications apportées au redémarrage. Je ne pense pas que vous ayez besoin de la complexité des autres solutions.


10 commentaires

Parce que pour certains temps limités, deux instances seront exécutées en parallèle (l'arrêt prend du temps). C'est ce que je veux éviter.


Vous devez donc éteindre et redémarrer ou réactiver l'application déjà en cours d'exécution (jetez un coup d'œil à la Linke que j'ai posté)?


@Smasher Dans ce cas, effectuez toutes les trucs d'arrêt que vous devez faire en mode instance unique, puis après que tout le travail d'arrêt est effectué, libérez le mutex et appelez Shellexecute.


@Smasher Tout ce que vous avez à faire est de mettre le shellexecute après la version mutex existante. Vraisemblablement, vous faites déjà tout le travail d'arrêt avant de libérer votre mutex existant?


@David: Non, je ne le fais pas et ce n'est pas si facile. Mais je suppose que vous avez raison que c'est la solution la plus facile.


@Smasher Je ne pense pas qu'il est difficile d'obtenir la libération de mutex comme dernière chose que vous faites. Dans tous les cas, si ce n'est pas alors vous déjà Avez-vous un problème, car une autre instance peut commencer après que vous avez publié le mutex, mais lorsque vous finissez toujours votre application.


@Smasher Par exemple, vous pouvez envisager d'utiliser System.ExitProc, mais il existe de nombreuses façons de y parvenir.


@DAVID: D'accord, je fais maintenant une variable globale redatartapp sur true et termine l'application (en envoyant wm_close à la fenêtre principale). À la fin de la source de projet (après Application.Run ), je publie le mutex, puis appelle shellexecute si le drapeau de redémarrage est défini. Malheureusement, Shellexecute semble échouer et tout ce que je reçois est un message de blocage Windows. Y a-t-il une raison pour laquelle je ne peux pas appeler shellexecute à cet endroit?


@Smasher Quelle poignée passez-vous à Shellexecute? Je voudrais juste passer null (= 0). Sinon, je ne peux pas penser au sommet de ma tête pourquoi cela échouerait.


Je passe déjà 0. étrange. Malheureusement, le débogueur n'est d'aucune aide ici.



1
votes

éditer ...

OK. Maintenant, je crois que je sais où est ton problème ... Vous avez des problèmes avec la finalisation des unités de programme!

Essayez d'ajouter à la section Programme comme première unité mon unité de redémarrure inférieure. xxx

; xxx

Lorsque vous souhaitez redémarrer l'application, définissez une variable redémarrer sur true et que résilier une application.

Étant donné que REDATETMUTEX a été ajouté en premier dans la section Programme, cela cousira que la finalisation de l'unité RedartMutex s'éloignera presque à la fin de la fermeture d'une application et toutes les autres unités feront la finalisation avant le redémarrage de l'unitéMutex, qui signifie que l'application peut recommencer à nouveau! < / p>


2 commentaires

"Même si je libère le mutex avant de commencer la deuxième instance, il ne fonctionnera pas car l'arrêt prend un certain temps et deux instance ne peuvent pas courir en parallèle" ... de la question.


@Smasher: Vous avez des problèmes avec la finalisation du programme! Chech ma réponse améliorée!



0
votes

Votre Releasemutex est probablement échoué puisque vous passez 'Faux' pour "Binitialowner" en appelant Createmutex . Soit avoir la propriété initiale du mutex ou appelez CLOSEHANDLE Au lieu de "REMEASEMUTEX" Passage de votre poignée mutex.


1 commentaires

Non, ne vous inquiétez pas de libérant le mutex du tout. La propriété du mutex est complètement non pertinente. Ce que vous devez faire est de détruire le mutex avec Couperhandle . C'est tout. (Ceci nécessite bien sûr de stocker la valeur de retour de créemutex .)



15
votes

Peut-être que vous devriez penser en dehors de la boîte. Au lieu de futzing avec la logique Mutex / Instance, vous pouvez simplement créer un autre exécutable qui attend que votre application se ferme puis la démarre à nouveau. En tant que bonus supplémentaire, vous pouvez utiliser ultérieurement ce mécanisme pour mettre à jour certaines des fichiers binaires de votre application principale. Il est également beaucoup plus facile de l'exécuter élevé au lieu de maintenir différents niveaux d'intégrité dans la même application, etc.


1 commentaires

+1; Ceci est un mécanisme que beaucoup d'applications font pour effectuer des mises à jour.



0
votes

Checkout de cette façon:

exécute simplement une nouvelle application et tue la curreuse une;

http://www.delphitricks.com/source-code/windows/ redémarrage_the_own_program.html


1 commentaires

Pour éviter les liens brisés, postez les informations pertinentes contenues dans le lien ici.



0
votes

(battre l'idée de sommeil)

Si vous souhaitez vous assurer que le processus d'origine est vraiment terminé / fermé avant de créer le mutex, une idée est de transmettre le PID au nouveau processus (la ligne de commande est la plus facile, toute autre méthode IPC fonctionne également). Ensuite, utilisez OpenProcess (synchroniser, False, PID) et WaitforsingleObject (j'utiliserais une boucle avec un délai d'attente (100 ms est une bonne valeur) et agissez en conséquence si le processus d'origine prend trop de temps)

Qu'est-ce que j'ai fini par faire, à côté de ce qui précède, c'était également créer une procédure de redémarrage dans la même unité avec le mutex et faire la logique là-bas, afin de conserver l'instance unique et de redémarrer la logique au même endroit (le Paramètre étant codé dur, vous ne voulez pas que des trucs codés sont dispersés autour de votre ou des applications.


0 commentaires