Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Probleme avec fopen et CreateFile sous windows

22 réponses
Avatar
Thomas Boidron
Bonjour,

j'ai un programme qui est dans C:\program files\MonProg\

qui crée un fichier option.txt (avec fopen ouCreatefile) lorquil est lancé.

Mon probleme est le suivant:


si je crée un racourci vers mon executable alors le fichier option.txt est
crée dans

le repertoire ou se trouve le raccourci au lieu d'etre crée dans le
repertoire ou se trouve l'executable.

Quelqu'un peut-il m'aider?

Merci d'avance.

10 réponses

1 2 3
Avatar
Arnaud Debaene
Thomas Boidron wrote:
Bonjour,

j'ai un programme qui est dans C:program filesMonProg

qui crée un fichier option.txt (avec fopen ouCreatefile) lorquil est
lancé.

Mon probleme est le suivant:


si je crée un racourci vers mon executable alors le fichier
option.txt est crée dans

le repertoire ou se trouve le raccourci au lieu d'etre crée dans le
repertoire ou se trouve l'executable.

Quelqu'un peut-il m'aider?

Tu dois vérifier le répertoire courant de ton exécutable avant de créer le

fichier, ou bien alors passer un chemin complet à fopen (ou CreateFile).

Arnaud

Avatar
Thomas Boidron
"Arnaud Debaene" a écrit dans le message news:
40b85913$0$17155$
Thomas Boidron wrote:
Bonjour,

j'ai un programme qui est dans C:program filesMonProg

qui crée un fichier option.txt (avec fopen ouCreatefile) lorquil est
lancé.

Mon probleme est le suivant:


si je crée un racourci vers mon executable alors le fichier
option.txt est crée dans

le repertoire ou se trouve le raccourci au lieu d'etre crée dans le
repertoire ou se trouve l'executable.

Quelqu'un peut-il m'aider?

Tu dois vérifier le répertoire courant de ton exécutable avant de créer le

fichier, ou bien alors passer un chemin complet à fopen (ou CreateFile).

Arnaud




Merci de ta réponse.
Mon probleme et que je ne peux pas connnaitre le chemin complet ( mon
programme peux etre deplacé sur le disque dur).
Donc comment faire pour connaitre le repertoire courant?


Avatar
Pierre Maurette
"Thomas Boidron" typa:


"Arnaud Debaene" a écrit dans le message news:
40b85913$0$17155$
Thomas Boidron wrote:
Bonjour,

j'ai un programme qui est dans C:program filesMonProg

qui crée un fichier option.txt (avec fopen ouCreatefile) lorquil est
lancé.

Mon probleme est le suivant:


si je crée un racourci vers mon executable alors le fichier
option.txt est crée dans

le repertoire ou se trouve le raccourci au lieu d'etre crée dans le
repertoire ou se trouve l'executable.

Quelqu'un peut-il m'aider?

Tu dois vérifier le répertoire courant de ton exécutable avant de créer le

fichier, ou bien alors passer un chemin complet à fopen (ou CreateFile).

Arnaud




Merci de ta réponse.
Mon probleme et que je ne peux pas connnaitre le chemin complet ( mon
programme peux etre deplacé sur le disque dur).
Si, et c'est la seule chose qui est en rapport avec le langage C++ (ou

C).

Donc comment faire pour connaitre le repertoire courant?
Si vous avez un prototype :

int main(int argc, char * argv[]);
argv[0] pointe sur le nom du programme selon la norme, cette chaine
est modifiable et persisante durant la durée du programme.
Ce nom est le chemin complet dans votre OS.
Si vous vous imposez un nom de programme (MonProg.exe) plus long ou de
même taille que option.txt (vous pourriez par exemple choisir
MonProg.ini), vous pouvez faire un truc du genre :
<code>
int main(int argc, char * argv[])
{
const char* sortie = "option.txt";
int L;
for(L = strlen(argv[0]); argv[0][L] != ''; --L){}
/* Comparer L+1 et strlen(sortie) */
argv[0][L+1] = '';
strcat(argv[0], sortie);
FILE* f = fopen(argv[0], "w");
/* bosser sur f */
fclose(f);
/* bosser */
return 0;
}
</code>
Vous pourriez même faire plus simple en nommant votre fichier de
sortie par exemple "MonProg.ex_".

Dans une appli GUI Windows, avec un WinMain(), la ligne de commande ne
contient pas le nom du programme. Mais stdlib.h définit _argc et _argv
(Borland, MinGW, etc.), __argc et __argv (Microsoft).

Ceci dit, et totalement off-topic, je suis étonné par votre problème.
Un raccourci sous Windows (clic droit / Propriétés) définit un champ
cible "chemin1MonProg.exe" et un champ Démarrer dans "chemin2". Si
chemin2 == chemin1, ce qui est le cas par défaut quand je crée un
raccourci sous XP, vous ne devriez pas avoir de problème même en
déplaçant le raccourci.
--
Pierre



Avatar
Arnaud Debaene
Thomas Boidron wrote:
<snip>

Merci de ta réponse.
Mon probleme et que je ne peux pas connnaitre le chemin complet ( mon
programme peux etre deplacé sur le disque dur).
Donc comment faire pour connaitre le repertoire courant?
<HS>GetCurrentDirectory et SetCurrentDirectory</HS>


Mieux vaut se méfier des solutions utilisant argv[0] : selon les OS, les
environnements, les shells utilisés, la manière dont le programme a été
lancé, etc..., le contenu de argv[0] n'est pas toujours fiable (c'est
parfois juste le nom du programme, parfois le chemin complet de
l'executable, j'en passe et des meilleures...)

Arnaud

Avatar
kanze
Pierre Maurette wrote in message
news:...

Donc comment faire pour connaitre le repertoire courant?



Impossible en C/C++ standard. Typiquement, il y a une requête système
pour ça. (getcwd() sous Unix, GetCurrentDirectory() or _getcwd() sous
Windows.)

Si vous avez un prototype :
int main(int argc, char * argv[]);

argv[0] pointe sur le nom du programme selon la norme, cette chaine
est modifiable et persisante durant la durée du programme.


Il y a selon la norme, et il y a ce que les implémentations font. Sous
Unix, en tout cas, c'est impossible à garantir que c'est le nom du
programme. Je crois que c'est également le cas sous Windows, avec
CreateProcess, on spécifie le chemin du programme séparemment de la
ligne de commande.

Ce nom est le chemin complet dans votre OS.


Peut-être. Ça dépend du système d'exploitation. La norme C++ exige autre
chose, mais ce qu'exige la norme C++ n'est pas implémentable ni sous
Windows, ni sous Unix.

De toute façon, et sous Windows et sous Unix, c'est le processus
appelant qui détermine le contenu de argv[0]. La convention est que les
« shells » passe le nom d'invocation (sous Unix) ou le chemin complet
(sous Windows), mais ce n'est qu'une convention, pas enforcée, et ça ne
vaut que pour les shells (et peut-être d'autres programmes systèmes).
Dans les deux cas, je n'ai pas le moindre problème à écrire un programme
qui lance ton programme avec un argv[0] qui n'a rien à voir.

Si vous vous imposez un nom de programme (MonProg.exe) plus long ou de
même taille que option.txt (vous pourriez par exemple choisir
MonProg.ini), vous pouvez faire un truc du genre :

<code>
int main(int argc, char * argv[])
{
const char* sortie = "option.txt";
int L;
for(L = strlen(argv[0]); argv[0][L] != ''; --L){}
/* Comparer L+1 et strlen(sortie) */
argv[0][L+1] = '';
strcat(argv[0], sortie);
FILE* f = fopen(argv[0], "w");
/* bosser sur f */
fclose(f);
/* bosser */
return 0;
}
</code>


Seulement si tu veux du code qui ne marche pas. Est-ce que tu connais le
C++ ? Ou même le C (parce qu'il n'y a rien de C++ dans ton code) ?

Enfin, ça ne marche pas chez moi, et je n'ai pas de mal à voir les cas
où il provoque l'équivalent d'un core.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
kanze
"Arnaud Debaene" wrote in message
news:<40baf1f6$0$23506$...
Thomas Boidron wrote:
<snip>
Mon probleme et que je ne peux pas connnaitre le chemin complet (
mon programme peux etre deplacé sur le disque dur). Donc comment
faire pour connaitre le repertoire courant?


<HS>GetCurrentDirectory et SetCurrentDirectory</HS>

Mieux vaut se méfier des solutions utilisant argv[0] : selon les OS,
les environnements, les shells utilisés, la manière dont le programme
a été lancé, etc..., le contenu de argv[0] n'est pas toujours fiable
(c'est parfois juste le nom du programme, parfois le chemin complet de
l'executable, j'en passe et des meilleures...)


C'est d'une part ; la norme C++ dit que c'est le nom qui a servi à
l'invocation (et non le chemin complet), mais c'est une partie de la
norme qu'on laisse d'à côté régulièrement, étant donné que c'est
impossible à imposer, ou sous Windows ou sous Unix.

De l'autre : quel rapport entre le répertoire courant et le chemin de
l'executable ? Que je sois sous Unix ou sous Windows, l'executable n'est
pour ainsi dire jamais dans le répertoire courant.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Pierre Maurette
typa:
[...]
Impossible en C/C++ standard. Typiquement, il y a une requête système
pour ça. (getcwd() sous Unix, GetCurrentDirectory() or _getcwd() sous
Windows.)
GetCurrentDirectory() ne résoud pas le problème. Il renvoie le même

chemin que celui dans lequel serait créé option.txt, par exemple par:
fopen("option.txt", "w");
ou
fopen("./option.txt", "w");
De plus, GetCurrentDirectory() demande à inclure windows.h, ce qui à
mon sens à éviter si c'est possible et que l'appli ne l'utilise pas
par ailleurs.

[...]
Seulement si tu veux du code qui ne marche pas. Est-ce que tu connais le
C++ ? Ou même le C (parce qu'il n'y a rien de C++ dans ton code) ?
Non, il n'y a rien de C++ dans ce code. Il se trouve que main() passe

un char**. Bon, il serait certainement judicieux de fabriquer dans la
phase d'initialisation une vraie string OptionsPath dans une classe
AppliVars. Mais ce n'était pas la question.

Enfin, ça ne marche pas chez moi, et je n'ai pas de mal à voir les cas
où il provoque l'équivalent d'un core.


A partir du message original ("C:program filesMonProg",
"raccourci") j'ai conclu à un environnement Windows (appli GUI ou
console). De plus, le problème est dans l'environnement. A noter que
je considère que le fait que le problème survient lors de
l'utilisation d'un raccourci est important. Donc soit je ne réponds
pas (c'est HS), soit je tente répondre à la question.
- Paramètres de la ligne de commande passés par le loader de Windows
(je ne parle pas de ce qui DOIT être passé par rapport à la norme,
mais de ce qui EST passé).
- _argc et _argv (ou __argc et __argv).
- Et surtout le champs "Démarrer dans" du raccourci.
Les trois voies proposées fonctionnent avec les versions Windows des
compilateurs Gcc, Borland et Microsoft. Mon message a donc une
probabilité sérieuse d'aider l'OP.
--
Pierre

Avatar
James Kanze
Pierre Maurette writes:

|> typa:
|> [...]
|> >Impossible en C/C++ standard. Typiquement, il y a une requête
|> >système pour ça. (getcwd() sous Unix, GetCurrentDirectory() or
|> >_getcwd() sous Windows.)

|> GetCurrentDirectory() ne résoud pas le problème. Il renvoie le même
|> chemin que celui dans lequel serait créé option.txt, par exemple
|> par:
|> fopen("option.txt", "w");
|> ou
|> fopen("./option.txt", "w");

Il a démandé le répertoire courant. C'est ce que renvoie
GetCurrentDirectory, au moins d'après la doc.

|> De plus, GetCurrentDirectory() demande à inclure windows.h, ce qui à
|> mon sens à éviter si c'est possible et que l'appli ne l'utilise pas
|> par ailleurs.

Et sous Unix, il faudrait inclure <unistd.h>. Il n'y a pas de solution
portable.

|> [...]
|> >Seulement si tu veux du code qui ne marche pas. Est-ce que tu
|> >connais le C++ ? Ou même le C (parce qu'il n'y a rien de C++ dans
|> >ton code) ?

|> Non, il n'y a rien de C++ dans ce code. Il se trouve que main()
|> passe un char**. Bon, il serait certainement judicieux de fabriquer
|> dans la phase d'initialisation une vraie string OptionsPath dans une
|> classe AppliVars. Mais ce n'était pas la question.

Le code, si je me rappelle bien, se servait aussi des FILE*, plutôt que
des streams. Et j'en passe.

|> >Enfin, ça ne marche pas chez moi, et je n'ai pas de mal à voir les cas
|> >où il provoque l'équivalent d'un core.

|> A partir du message original ("C:program filesMonProg",
|> "raccourci") j'ai conclu à un environnement Windows (appli GUI ou
|> console).

Mais ça ne marche pas sous Windows. J'ai essayé sur une machine sous NT
4, par exemple, et ça a fait à peu près n'importe quoi.

Le problème est simple : ni Windows ni Unix ne font une garantie sur ce
que tu trouves en argv[0]. Tous les deux le laisse à l'appelant. Comme
j'ai dit, la *convention* veut qu'un shell passe le chemin complet sous
Windows, le nom de l'invocation sous Unix. Mais ce n'est qu'une
convention ; si ton programme n'est jamais lancé qu'à partir d'un
fichier .bat ou un script de shell, ou par un clique sur un bouton, ça
va. Mais au moins sous Windows ou sous Unix, ce n'est pas la seule façon
de lancer un programme.

Et le problème de ton programme, ou au moins un des problèmes, c'est
qu'il accède en dehors des zones permises si argv[0] ne contient pas
vraiment le chemin complet.

|> De plus, le problème est dans l'environnement. A noter que je
|> considère que le fait que le problème survient lors de l'utilisation
|> d'un raccourci est important. Donc soit je ne réponds pas (c'est
|> HS), soit je tente répondre à la question.

|> - Paramètres de la ligne de commande passés par le loader de Windows
|> (je ne parle pas de ce qui DOIT être passé par rapport à la norme,
|> mais de ce qui EST passé).

Les paramètres passés par le loader de Windows sont ceux que le
programme appelant a passé à spawn ou à CreateProcess. Si le programme
qui invoque le tien passe le chemin complet, ça marche. S'il passe autre
chose, tu as autre chose.

|> - _argc et _argv (ou __argc et __argv).
|> - Et surtout le champs "Démarrer dans" du raccourci.

Mais tu n'as pas l'air de comprendre que la majorité des programmes ne
sont pas lancés à partir d'un raccourci sur l'écran. Regarde la liste
des processus actifs, par exemple -- il y en a bien une vingtaine, au
minimum, sans que tu n'as jamais cliqué sur un raccourci.

Or, le problème avec ton approche, c'est que pour les tests, on va sans
doute utilisé un raccourci, ou le démarrer depuis le Visual Studio, qui
sans doute lui aussi initialise les paramètres comme tu le veux. Alors,
ça ne serait qu'une fois le programme déployé qu'on se rendrait compte
de l'erreur.

|> Les trois voies proposées fonctionnent avec les versions Windows des
|> compilateurs Gcc, Borland et Microsoft.

Je repète : ils ne fonctionnent sous Windows NT avec VC++ 6.0. Ils ne
fonctionnent que dans des cas bien précis, qui sont loin de representer
toutes les possibilités d'invocation d'un programme.

|> Mon message a donc une probabilité sérieuse d'aider l'OP.

Justement, je crois que ça risque de lui poser plus de problèmes que ça
en résoud. Ce n'est pas parce que quelque chose à l'air de fonctionner
avec un test trivialement simple qu'il fonctionne. Tu lui prépares des
problèmes pour l'avenir.

Qu'il prenne ton style de programmation comme modèle ne lui aiderait pas
non plus.

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Avatar
Arnaud Debaene
wrote:
"Arnaud Debaene" wrote in message
news:<40baf1f6$0$23506$...

De l'autre : quel rapport entre le répertoire courant et le chemin de
l'executable ? Que je sois sous Unix ou sous Windows, l'executable
n'est pour ainsi dire jamais dans le répertoire courant.


L'OP n'était pas trop clair de de savoir s'il voulait créer son fichier
option.txt dans le répertoire courant ou bien dans le répertoire de
l'executable.
Dans les 2 cas, c'est une solution spécifique à l'OS : GetCurrentDirectory
pour le répertoire courant ou GetModuleFileName(NULL) pour le répertoire de
l'executable.

Arnaud

Avatar
Pierre Maurette
"Arnaud Debaene" typa:

wrote:
"Arnaud Debaene" wrote in message
news:<40baf1f6$0$23506$...

De l'autre : quel rapport entre le répertoire courant et le chemin de
l'executable ? Que je sois sous Unix ou sous Windows, l'executable
n'est pour ainsi dire jamais dans le répertoire courant.


L'OP n'était pas trop clair de de savoir s'il voulait créer son fichier
option.txt dans le répertoire courant ou bien dans le répertoire de
l'executable.
Dans les 2 cas, c'est une solution spécifique à l'OS : GetCurrentDirectory
pour le répertoire courant ou GetModuleFileName(NULL) pour le répertoire de
l'executable.
En fait, il me semble clair que Thomas veut que option.txt continue à

être créé dans le répertoire de l'exécutable. Son problème vient du
fait qu'à un moment il a édité un raccourci à la main (par exemple),
et que le répertoire courant n'est plus celui de l'exécutable. Il me
semble que le répertoire courant d'un process lancé par un raccourci
est dans le champs "Démarrer dans" s'il est renseigné, et par défaut
celui du raccourci.
Ce qui est moins clair, c'est la position de Thomas par rapport à
MonProg. Est-ce un programme de son cru? Souhaite-t-il le modifier? Je
veux dire que le fait que le répertoire courant et le répertoire de
l'exécutable soient différents peut avoir d'autres conséquences. Le
mieux est peut-être de faire en sorte que les deux chemins soient les
mêmes, comme c'était le cas, ce qui est facile en regardant ce qu'est
un raccourci. C'est même comme ça qu'il est fait par défaut par clic
droit/créer un raccourci.
Corrigez-moi si je me trompe: le répertoire courant défini par le
lancement d'un programme est stable, en ce sens que c'est une variable
propre au process que lui seul peut ultérieurement modifier.
Le programme "Agent", celui que j'utilise actuellement, utilise le
champs "Démarrer dans" pour n'autoriser qu'une instance par compte,
mais autant d'instances qu'il y a de comptes.
--
Pierre


1 2 3