2 votes

Le E/S de fichier ne fonctionne pas si l'application parent est lancée par une application dans un répertoire différent.

OK - c'est un scénario très bizarre, et j'ai des problèmes pour essayer d'en comprendre le fond.

J'ai 2 applications (disons simplement app1 et app2) et un fichier texte (txt1).
App1 et txt1 résident dans le même répertoire (disons C:\APP), mais app2 réside dans un sous-répertoire du répertoire de app1 (C:\APP\SUB).

Quand App1 démarre, il lit des choses de txt1 en utilisant le standard :

AssignFile(txtFile,'txt1.txt');
Reset(txtFile);

Aucun problème avec ça. Cependant, quand App2 lance App1 via une commande shellexecute :

shellexecute(0,'open','..\app1.exe',nil,nil,SW_SHOW);

App1 ne semble pas voir le fichier texte. J'obtiens une réponse disant 'Fichier spécifié introuvable'. Bizarre.

J'ai débuggué en ajoutant :

if not fileexists('txt1.txt') then
showMessage(ExtractFilePath(application.exename));

Et cela montre le bon chemin du fichier de app1 (lui-même), donc, pourquoi alors, la commande 'reset' produit l'erreur 'Introuvable....'? Je me demande si utiliser shellexecute fait en sorte que l'application pense d'une manière ou d'une autre qu'elle s'exécute à partir du sous-répertoire plutôt que du répertoire réel dans lequel elle se trouve?

Je comprends que la solution la plus simple est d'ajouter simplement le chemin du fichier au début de chaque fichier que mon 'app1' ouvre (j'ai essayé et oui, ça fonctionne correctement), cependant, en réalité, il y a des centaines de fichiers auxquels cette application principale accède par une méthode similaire (que ce soit des fichiers txt, ini ou dll) c'est-à-dire en attribuant le fichier en fonction du fait qu'il se trouve dans le même répertoire que l'application, donc sans spécifier le chemin complet du fichier, donc les changer (et les maintenir) tous n'est pas quelque chose qui nous intéresserait de faire à ce moment.

Est-ce que quelqu'un a déjà vu quelque chose comme ça auparavant? Y a-t-il un meilleur moyen pour moi de faire lancer App2 lance App1 autre que ShellExecute? Il n'y a pas de paramètres ou quoi que ce soit à transmettre à App1, j'ai juste besoin qu'il démarre.

Merci pour votre temps - faites moi savoir si vous avez besoin de quelque chose d'autre sur ce sujet!

5voto

David Heffernan Points 292687

Par défaut, les nouveaux processus héritent du répertoire de travail du processus parent. Bien sûr, vous n'avez pas besoin d'utiliser ce répertoire par défaut, mais votre code le fait. Et les chemins relatifs sont relatifs au répertoire de travail. Ainsi, le deuxième processus hérite du répertoire de travail du premier, et cherche donc les fichiers au mauvais endroit.

Le problème fondamental est que vos programmes dépendent de la valeur du répertoire de travail. Mais le fichier texte n'est pas situé dans le répertoire de travail. Il se trouve dans le même répertoire que son exécutable associé. Vous avez simplement eu de la chance lorsque ces deux répertoires ont coïncidé.

Vous devriez donc arrêter d'utiliser des chemins relatifs, et commencer à utiliser des chemins absolus complets qui sont construits en utilisant le chemin de l'exécutable.

FileName := ExtractFilePath(ParamStr(0)) + 'txt1.txt';

Le même problème existe dans la façon dont vous appelez ShellExecute. Encore une fois, vous dépendez du répertoire de travail. Le nom du fichier exécutable que vous devez utiliser est :

ExtractFilePath(ParamStr(0)) + '..\app1.exe'

Bien que vous ayez accepté une réponse suggérant de spécifier le répertoire de travail lors de la création du nouveau processus, c'est la mauvaise solution. Le fichier se trouve dans le même répertoire que l'exécutable, c'est donc ainsi que vous devriez le trouver.

La façon dont votre code dépend de son répertoire de travail impose une exigence inutile et contraignante aux processus appelants. À savoir qu'ils doivent spécifier un répertoire de travail identique au répertoire de l'exécutable. Vous ne devriez tout simplement pas exiger cela de vos appelants, ne serait-ce que parce qu'il n'y a aucune raison de le faire.

Attention également, pour un programme GUI, le répertoire de travail peut bien changer pendant l'exécution. Par exemple lorsque vous utilisez une boîte de dialogue de fichier. Pour une application console, le répertoire de travail peut être considéré comme un paramètre d'entrée. Pour un programme GUI, ce n'est pas le cas.

3voto

OnTheFly Points 1901

L'argument facultatif lpDirectory de la fonction ShellExecute permet au client de spécifier un répertoire de travail pour le programme à exécuter.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X