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

Problème avec GetOpenFileName

15 réponses
Avatar
Roger
Bonjour,
J'ai un problème avec GetOpenFileName si et seulement si le fichier que
j'ouvre fait plus de 93Ko !!!! Si j'ai fait une erreur de programmation vous
allez pouvoir la trouver très vite car j'ai réécrit un programme élémentaire
très simple et très court qui reproduit exactement le phénomène et vous en
trouverez le code complet ci-dessous.
Ce programme est une simple fenêtre avec deux boutons (un bouton "Ouvrir" et
un bouton "Fermer") Le bouton "Ouvrir" (case 1 ) appelle la fonction
GetOpenFileName pour choisir un fichier quelconque, puis ouvre le fichier
avec CreateFile, puis lit un premier bloc de 1024 bytes avec ReadFile et
c'est tout. Le bouton "Fermer" (case 2) permet de fermer le fichier qui
vient d'être ouvert. Vous pouvez recopier ce code, le jeu consiste à faire
l'expérience en choisissant un premier fichier d'environ 75Ko, vous l'ouvrez
avec le bouton Ouvrir, puis vous le fermez avec le bouton "Fermer" et vous
recommencez plusieurs fois avec le même fichier : Ouvrir, Fermer, etc...
ceci sans jamais cliquer sur la croix pour fermer la fenêtre, vous
constaterez qu'il n'y a aucun problème, tout marche très bien. Puis vous
recommencez en choisissant cette fois-ci un fichier d'environ 1 Mo (>93Ko
c'est suffisant, mais avec 1Mo ça va plus vite), vous allez constater à un
moment (ou même souvent dès le premier essai) que le message 2 s'affiche
puis disparaît tout seul (très curieux alors que MessageBox est bloquant)en
même temps que la fenêtre. Je serais ravi que vous trouviez la faille car je
ne vois pas de rapport avec la taille du fichier puisque dans tous les cas
je ne lis que le 1er bloc, ci-dessous le petit programme :

#include <windows.h>
LRESULT CALLBACK processmainmess( HWND, UINT, WPARAM, LPARAM);
HINSTANCE n0instance;
MSG message;
OPENFILENAME ofn;
int APIENTRY WinMain( HINSTANCE W_n0inst, HINSTANCE W_n0precinst, LPTSTR
W_CmdLine, int W_cdeaffich) // entier signé (32 bits)
{
n0instance = W_n0inst;

WNDCLASS winclassmain;
winclassmain.hInstance = n0instance;
winclassmain.lpszMenuName = NULL;
winclassmain.lpszClassName = "Essai";
winclassmain.hIcon = NULL;
winclassmain.hCursor = LoadCursor(NULL,IDC_ARROW);
winclassmain.hbrBackground =(HBRUSH)(COLOR_WINDOW+1);
winclassmain.style = CS_VREDRAW | CS_HREDRAW;
winclassmain.lpfnWndProc = (WNDPROC)processmainmess;
winclassmain.cbWndExtra = 0;
winclassmain.cbClsExtra = 0;
if ( !RegisterClass( &winclassmain ) )
return( FALSE );
//
HWND Hdlgmain = CreateWindow("Essai", "test", WS_CAPTION |
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 250, 100, NULL, NULL,
n0instance, NULL);
if ( !Hdlgmain ) return( FALSE );
ShowWindow( Hdlgmain, W_cdeaffich ); // lancement manuel
UpdateWindow( Hdlgmain ); //
while(GetMessage( &message, NULL, 0, 0))
{
TranslateMessage( &message );
DispatchMessage( &message );
}
return message.wParam;
}
LRESULT CALLBACK processmainmess( HWND winmainkey, UINT IDMsg, WPARAM
wParam, LPARAM lParam )
{
static HANDLE keyfile;
CHAR cheminfile[256];
static BOOL fileexist;
DWORD nbbytetoread=1024;
DWORD nbbyteread;
static CHAR Bloc[1025];
switch(IDMsg)
{
case WM_CREATE :
CreateWindow("BUTTON", "Ouvrir", WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0,
100, 35, winmainkey, (HMENU)1, n0instance, NULL);
CreateWindow("BUTTON", "Fermer", WS_CHILD | WS_VISIBLE | WS_BORDER, 110, 0,
100, 35, winmainkey, (HMENU)2, n0instance, NULL);
fileexist=false;
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case 1: // clic sur bouton ouvrir un fichier
if(fileexist) {MessageBox(winmainkey, "Fichier déjà ouvert", "test", MB_OK);
break;}
// *** choix du Fichier à ouvrir
ZeroMemory(&ofn, sizeof(OPENFILENAME));
*cheminfile=0x0;
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = winmainkey;
ofn.lpstrFile = cheminfile;
ofn.nMaxFile = 256;
ofn.lpstrFilter = "Tous les fichiers (*.*)\0*.*\0\0";
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
//
MessageBox(winmainkey, "1", "je passe", MB_OK); // ************* piège
message 1
if (GetOpenFileName(&ofn)==false) break;
MessageBox(winmainkey, "2", "je passe", MB_OK); // ************* piège
message 2
//
keyfile = CreateFile(cheminfile, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
fileexist=true;
ReadFile(keyfile, Bloc, nbbytetoread, &nbbyteread, NULL);
MessageBox(winmainkey, "Fichier ouvert et 1er bloc lu OK", "test", MB_OK);
break;
case 2: // clic sur bouton fermer le fichier déjà ouvert
if(!fileexist) {MessageBox(winmainkey, "Il n'y a pas de fichier ouvert",
"test", MB_OK); break;}
CloseHandle(keyfile);
fileexist=false;
MessageBox(winmainkey, "Fichier fermé OK", "test", MB_OK);
break;
}
break;
case WM_CLOSE :
DestroyWindow( winmainkey );
break;
case WM_DESTROY :
if(fileexist) CloseHandle(keyfile);
PostQuitMessage(0);
break;
case WM_QUERYENDSESSION :
DestroyWindow( winmainkey );
break;
default :
return DefWindowProc( winmainkey, IDMsg, wParam, lParam );
};
return 0;
}

10 réponses

1 2
Avatar
Jean-Christophe
On Jun 13, 10:42 pm, "Roger"

CreateFile(cheminfile, GENERIC_READ | GENERIC_WRITE



Pourquoi GENERIC_WRITE ?
Avatar
Roger
Merci pour la réponse
Pourquoi GENERIC_WRITE ?
Il n'y a pas de raison particulière, j'ai simplement fait un copié-collé de
cette fonction d'un autre programme, le Generic_write ne me gênait pas pour
ce que je voulais faire. Mais le problème ne vient pas de là, sinon j'aurais
le phénomène que j'ai indiqué sur n'importe quel fichier, or avec les petits
fichiers <90 Ko je n'ai aucun problème. J'ai toutefois fait l'essai de
l'enlever et ça ne change rien au phénomène. Par contre j'ai remarqué que si
dans les paramètres de la structure OPENFILENAME, j'enlève la ligne:
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
et que lorsque je choisis le fichier je coche la case: "read only" j'ai le
problème nettement moins souvent, je ne vois pas le rapport, mais je l'ai
quand même (toujours avec les gros fichiers), donc ça ne résout pas le
problème, heureusement d'ailleurs parce sinon il faudrait trouver pourquoi.
Avatar
CriCri
Salut

J'ai copié-collé ton chtit prog et je n'ai pas constaté ton problème.
Le plantage donne l'impression que tu amorces une bombe à retardement en
amont - mais je n'ai pas épluché ton code: trop pénible à relire sans
aucun formatage :-(((

Ceci dit j'ai remarqué quand même que tu t'exposes à tous les malheurs:
- tu présumes allégrement que ton fichier a été correctement ouvert
sans examiner le résultat renvoyé par CreateFile(), et tu procèdes ainsi
à sa lecture en utilisant un handle qui n'est pas forcément valide...
- tu présumes que les données ont été correctement lues sans examiner
le résultat renvoyé par ReadFile() (ni ce qui a été écrit dans le
buffer - peut-être rien!) - donc tu ne sais pas si ça s'est bien passé...

Alors (et surtout puisque le plantage peut ne se produire qu'après
quelques tours du manège), regarde un peu plus attentivement exactement
ce qui se passe: peut-être t'enfonces-tu progressivement dans la m____
en poursuivant aveuglement ton chemin malgré des erreurs que tu n'as ni
détectées ni gérées.

Cdlt
CC

PS - heu, je suppose que tu fais toussa en mode debug? - rien ne
permet de tracer ce qui se passe?

--
bitwyse [PGP KeyID 0xA79C8F2C]
http://www.le-maquis.net
C'est comme au CNRS: des chercheurs qui cherchent on en trouve
mais des chercheurs qui trouvent on en cherche.
Avatar
Roger
"CriCri" a écrit dans le message de news:
4df79a72$0$14675$
Salut

J'ai copié-collé ton chtit prog et je n'ai pas constaté ton problème.
Le plantage donne l'impression que tu amorces une bombe à retardement en
amont - mais je n'ai pas épluché ton code: trop pénible à relire sans
aucun formatage :-(((

Ceci dit j'ai remarqué quand même que tu t'exposes à tous les malheurs:
- tu présumes allégrement que ton fichier a été correctement ouvert
sans examiner le résultat renvoyé par CreateFile(), et tu procèdes ainsi
à sa lecture en utilisant un handle qui n'est pas forcément valide...
- tu présumes que les données ont été correctement lues sans examiner
le résultat renvoyé par ReadFile() (ni ce qui a été écrit dans le
buffer - peut-être rien!) - donc tu ne sais pas si ça s'est bien passé...



Merci pour la réponse, mais ce petit programme je l'ai écrit spécialement
pour mettre le problème en évidence, car ça n'est pas avec ce petit
programme au départ que j'ai rencontré ce problème, c'est avec un programme
beaucoup plus gros et (+ de 2000 lignes de code) que je l'ai rencontré, et
dans ce plus gros programme mieux fini je teste tous les codes retour de
CreateFile, ReadFile etc... et malgré ça et tous les pièges que j'ai mis
dans tout les coins, je n'ai pas pu trouver la cause du phénomène. C'est
alors que j'ai décidé de m'adresser à ce news, mais décemment je ne pouvais
pas vous poster 2000 lignes de code, alors j'ai écrit ce petit programme
spécialement pour le news en simplifiant au maximum et effectivement en
enlevant les tests, mais ils y sont bien à l'origine.
A+
Avatar
Laurent
"CriCri" a écrit dans le message de news:
4df79a72$0$14675$
Salut

J'ai copié-collé ton chtit prog et je n'ai pas constaté ton problème.



Pareil, testé avec gros fichiers, aucun problème..
Avatar
Roger
"Laurent" a écrit dans le message de news:
it8hfo$qh$
"CriCri" a écrit dans le message de news:
4df79a72$0$14675$
Salut

J'ai copié-collé ton chtit prog et je n'ai pas constaté ton problème.



Pareil, testé avec gros fichiers, aucun problème..
Merci d'avoir fait le test et de m'en avoir informé, mais j'aurais préféré
que tu rencontres le même problème et que tu me dises: c'est normal parce
que tu as fait telle erreur de programmation !!! Si mon programme marche
ailleurs c'est que malheureusement il est bon et dans ce cas je suis bien
embêté car si ça ne vient pas du programme d'où cela peut-il venir chez moi
?!!! Ma version Windows ???!!! j'ai Windows XP version familiale SP3


Version5.1 (numéro 2600.xpsp_sp3_gdr.101209-1647: Service Pack 3)
Ma question n'est donc plus: où est l'erreur dans mon programme, mais plutôt
quelqu'un a-t-il une idée sur la raison pour laquelle ce programme là se
comporte ainsi chez moi ???
Merci
Avatar
Christian ASTOR
Roger a écrit :

Merci d'avoir fait le test et de m'en avoir informé, mais j'aurais préféré
que tu rencontres le même problème et que tu me dises: c'est normal parce
que tu as fait telle erreur de programmation !!! Si mon programme marche
ailleurs c'est que malheureusement il est bon et dans ce cas je suis bien
embêté car si ça ne vient pas du programme d'où cela peut-il venir chez moi
?!!! Ma version Windows ???!!! j'ai Windows XP version familiale SP3


Version5.1 (numéro 2600.xpsp_sp3_gdr.101209-1647: Service Pack 3)
Ma question n'est donc plus: où est l'erreur dans mon programme, mais plutôt
quelqu'un a-t-il une idée sur la raison pour laquelle ce programme là se
comporte ainsi chez moi ???



Même config, XP SP3, mais impossible à reproduire le comportement que tu
décris.
Une MessageBox qui se ferme toute seule ?!
(à part appuyer sur [Enter] trop longtemps/rapidement sur la précédente,
mais bon...)
Avatar
Roger
"Christian ASTOR" a écrit dans le message de
news: it8ldr$l2s$
Roger a écrit :

Même config, XP SP3, mais impossible à reproduire le comportement que tu
décris.
Une MessageBox qui se ferme toute seule ?!
(à part appuyer sur [Enter] trop longtemps/rapidement sur la précédente,
mais bon...)

Encore merci d'avoir fait le test, si un jour je trouve je vous tiendrai au
courant, mais en attendant je suis bloqué. A propos de la MessageBox qui se
ferme toute seule, j'avais imaginé un truc mais je ne sais pas ce que ça
vaut:


Quand je demande à lire un seul bloc (le premier de 1024 octets), je suis au
niveau utilisateur et Windows ne m'en passe effectivement que 1024. Mais que
se passe-t-il au niveau hardware? pour avoir fait il y a très longtemps de
la programmation système en assembleur sur des Cyber de chez Control Data,
il me semble me souvenir qu'au plus bas niveau système on lit quand même au
minimum un secteur entier du disque même si aux plus hauts niveaux on n'en
passe que le bout demandé à l'utilisateur. Imaginons qu'une fois les 1024
octets passés à l'utilisateur et le MessageBox affiché, la lecture se
poursuivant au plus bas niveau jusqu'à la fin du secteur, il y ait
maintenant une erreur quelconque, est-ce que ça ne pourrait pas expliquer la
disparition de ma MessageBox ?
Je n'ai jamais fait de programmation système sur micro pour la bonne raison
que lorsque j'en faisais les micros n'existaient pas encore, mais à ton avis
est-ce que ce raisonnement tient debout.
En tout cas si c'est un truc comme ça, je ne vois pas comment le piéger.
Avatar
CriCri
Roger a écrit :
Imaginons qu'une fois les 1024 octets passés à l'utilisateur et le
MessageBox affiché, la lecture se poursuivant au plus bas niveau
jusqu'à la fin du secteur, il y ait maintenant une erreur
quelconque, est-ce que ça ne pourrait pas expliquer la disparition de
ma MessageBox ?



Nous sommes à un niveau d'abstraction loin au-dessus des fonctions de
MS-DOS et le FAT16/32 ;-)
AMHA - vu la vitesse des DD et la mémoire disponible de nos jours -
1. la lecture du secteur sera terminé très longtemps avant que tu aies
le temps de voir ton MessageBox apparaître à l'écran (encore moins
disparaître...).
2. il y a toutes les chances que tant qu'il y est le système lira non
seulement 1024 bytes, ni même un seul petit secteur; mais tout un bloc
en cache (en anticipant la prochaine requête...).

Tu pourrais augmenter la taille de ton buffer pour correspondre à un
secteur entier de ton DD (selon son formatage) - voire plusieurs - et
demander ça pour voir si ça change quelque chose. (Demande un MO pour
voir, pourquoi pas?)

Je ne sens pas la théorie que c'est la taille du fichier qui compte...
Tes gros fichiers n'auraient-ils rien d'autre en commun?
('FILE_SHARE_READ' m'intrigue aussi... pourquoi partager le fichier que
tu ouvres? - ça complique l'affaire.)

Pour essayer de diagnostiquer ce qui déclenche le problème en réduisant
les variables, je te suggère de créer un fichier texte de petite taille
(75kO...), puis le sauvegarder doublé, triplé etc... dans le même
dossier et en conservant tous les mêmes attributs, droits etc.

Si tu veux tu peux m'envoyer ton exécutable et un/des fichiers qui
provoquent le plantage pour tester chez moi (on ne sait jamais).
(Passe par le formulaire de contact sur mon site ou sinon je te donnerai
une adresse FTP pour uploader.)

Cdlt, CC

--
bitwyse [PGP KeyID 0xA79C8F2C]
http://www.le-maquis.net
C'est comme au CNRS: des chercheurs qui cherchent on en trouve
mais des chercheurs qui trouvent on en cherche.
Avatar
Roger
Si tu veux tu peux m'envoyer ton exécutable et un/des fichiers qui
provoquent le plantage pour tester chez moi (on ne sait jamais).
(Passe par le formulaire de contact sur mon site ou sinon je te donnerai
une adresse FTP pour uploader.)

Cdlt, CC


Merci, je retiens la proposition, mais impossible d'envoyer quoi que ce
soit, erreur 404 à chaque fois, aussi bien avec Internet Explorer qu'avec
Firefox, petit ou gros fichier.
Peut-ête avec une simple adresse mail....
RG
1 2