Supprimer un fichier | récupérer son extension


Propriétés du code


Date de création : 31/12/2006 à 01:36:00
24 Commentaire(s)
  MadMatt

 

Présentation


Voilà 2 fonctions que j'ai à la base trouvé dans la classe de Violent_Ken sur les fichiers. J'ai changé les noms des variables pour qu'elle correspondent plus au reste.

La fonction FileExists est donnée à l'adresse :
http://vbsystemlibrary.free.fr/code.php?ID=23

 

Code


Public Declare Function SetFileAttributes Lib "kernel32.dll" Alias "SetFileAttributesA" (ByVal lpFileSpec As String, ByVal dwFileAttributes As Long) As Long
Public Declare Function PathFindExtension Lib "shlwapi" Alias "PathFindExtensionA" (ByVal pPath As String) As Long
Public Declare Function DeleteFile Lib "kernel32" Alias "DeleteFileA" (ByVal lpFileName As String) As Long
Public Const FILE_ATTRIBUTE_NORMAL As Long = &H80


'---------------------------------------------------------------------------------------
' Procedure : KillFile
' DateTime  : 31/12/2006 01:23
' Author    : Vb System Library
' Purpose  : Supprime un fichier
' Params    : FullPath : Chemin d'accès au fichier
'---------------------------------------------------------------------------------------
Public Function KillFile(ByRef FullPath As String)
    ' Supprime un attribut qui empecherait la suppression
    SetFileAttributes FullPath, FILE_ATTRIBUTE_NORMAL
    KillFile = DeleteFile(FullPath)
End Function


'---------------------------------------------------------------------------------------
' Procedure : GetFileExtension
' DateTime  : 31/12/2006 01:29
' Author    : Vb System Library
' Purpose  : Renvoie l'extension du fichier
' Params    : FileName : Nom du fichier
'---------------------------------------------------------------------------------------
Public Function GetFileExtension(ByVal FileName As String) As String
    Dim Ptr As Long
    Ptr = PathFindExtension(FileName)
    GetFileExtension = String$(lstrlen(Ptr), 0)
    lstrcpy ByVal GetFileExtension, ByVal Ptr
End Function


 

Historique


Voici l'historique des modifications de ce code :
Le 02/01/2007 par MadMatt : Modif du titre et optimisations
Le 02/01/2007 par MadMatt : 1 seul appel à lapi PathFindExtension

 
 

Modifier le code

Seul les admins et l'auteur du code lui même peuvent modifier ce code.

 

Commentaires


De MadMatt le 31/12/2006 à 01:40


Par contre il reste encore des points à voir pour ces fonctions :

1_ Faut-il tester l'existence du fichier avant de le supprimer ? l'api ne soulèvera pas d'erreur, alors est-ce plus utile, on pourrait peut etre gagner du temps ?
2_ Y'avait un "On error resume next" dans la fonction KillFile à l'origine, en rajoutant le If FileExists, je l'ai supprimé. Mais si Violent_Ken passe par la s'il pouvait nous expliquer pourquoi il l'avait mis ?

3_ Pour GetFileExtension, on a 2 appel à l'API, ça pourrait etre contourné en l'appelant 1 fois, en stockant l'adresse mémoire dans une variable, puis en faisant une copie de ce style :
http://www.vbfrance.com/codes/RECUPERER-CHAINE-CARACTERE-PARTIR-SON-POINTEUR-ADRESSE-MEMOIRE_38998.aspx

Voilà dites moi ce que vous en pensez
A+

 

De violent_ken le 01/01/2007 à 23:46


Op, op, op.... désolé d'avoir été absent pendant un bon bout de temps (temps passé à coder un bout de mon éditeur hexa), me re-voici ;)


Alors :

1) Private Const FILE_ATTRIBUTE_NORMAL As Long = &H80
2) je ne pense pas que le test de présence du fichier soit nécessaire car tu l'as dit, l'API se contente de retourner 0 si fichier est inexistant
3) tu as bien fait d'avoir enlevé On Error..., c'était un oubli de ma part (coze' of ctr+V/ctrl+C)
4) Pour le GetFileExtension, je ne sais pas vraiment si l'autre méthode gagnerait du temps processeur, c'est à tester ;)
@+

 

De MadMatt le 02/01/2007 à 00:19


Voilà les améliorations ont été faites merci pour les infos ;)

 

De sebdraluorg le 02/01/2007 à 18:03


Eh wai comme tu l'as dis il suffit de stoker le retour de PathFindExtensionA plutot que de l'appeler deux fois ce qui doit quand meme etre beaucoup plus lent..

Sinon pour KillFile, le probleme si tu ne verifie pas c'est que comme l'as dit Violent_Ken DeleteFileA renverra 0 si le fichier n'existe pas, et donc ta fonction va renvoyer que le fichier n'a pas été supprimé ce qui peut porter a confusion pour l'utilisateur final...

 

De MadMatt le 02/01/2007 à 18:15


Pour le double appel à PathFindExtension je vais y remplacer tant qu'à faire.

Sinon pour KillFile, j'aurai une question d'ordre totalement général : en principe, si une fonction réussi, elle renvoie quoi comme valeur ?
Car la l'api DeleteFile renvoie 0 si elle foire (quelque soit l'erreur), et pas 0 si elle réussi.

 

De violent_ken le 02/01/2007 à 18:44


De manière générale, çà dépend.

Soit le 0 <==> NO_ERROR et -1 <==> ERROR
Soit 0 <==> ERROR et n>0 <==> NO_ERROR


Dans tout les cas, le plus clair est je pense :
1 : supprimé
0 : n'a pas supprimé
-1 : échec de la suppression

 

De MadMatt le 02/01/2007 à 18:56


Ok donc c'est bien ce que je pensais, y'a 2 "standards" opposés. Faudrait en choisir un qu'on applique dans toute la librairie, par exemple 0 : error / 1 : pas d'erreur. Et on applique ça sur toutes les fonctions qui le peuvent.

 

De sebdraluorg le 02/01/2007 à 18:59


wai c'est vrai que c'est assez ambigu vu que 0 = ERROR_SUCCESS

En fait y a plusieurs sorte de retour,
-Les hError qui renvoyent un vrai code de retour que tu peux convertir en message d'erreur par un FormatMessage
-Les retour True/False qui renvoyent juste 1 en cas de reussite et 0 en cas d'echec.
-Les retour Handle qui renvoyent un Handle en cas de reussite et 0 en cas d'erreur...

Etc...

 

De violent_ken le 02/01/2007 à 19:03


Exact...


En tout cas, ce qui est toujours valable il me semble, c'est -1 en cas d'erreur (sauf pour l'API GetCurrentProcess et son homologue avec le thread).

 

De MadMatt le 02/01/2007 à 19:05


Mais alors que choisir comme code de retour ?
Parce que si on se retrouve avec une api qui ne renvoie pas de code d'erreur mais juste "erreur" par exemple, et qu'on choisit de renvoyer un hError, on a pas de hError à renvoyer.
Et si on choisit de renvoyer seulement "erreur" ou "pas d'erreur", l'utilisateur n'a pas de description d'erreur.

-1 comme code d'erreur c'est pas mal, ça prete pas à confusion

 

De violent_ken le 02/01/2007 à 19:14


Oui, et c'est pourquoi certaines API renvoient -1, d'autres 0 et d'autres encore un code d'erreur.

Donc a priori il est impossible de faire une règle générale...



Mais nous devons unifier ce point à tout le projet, se serais beaucoup mieux.


Je propose (dites moi ce que vous en pensez) :
-toutes les fonctions qui échouent renvoie -1
-toutes celles qui réussissent renvoient n>0 (1 quand le résultat n'est pas réutilisé)
-le 0 est renvoyé si la fonction n'a pas travaillé.


Après, il faut faire d'autres choix. Exemple avec un KillFile.
Doit on privilégier uniquement la vitesse, ou alors le résultat renvoyé ?

*) Le choix de la vitesse amène à ne pas tester l'existence du fichier, ce qui importe est sa suppression
*) Le choix du résultat amènerait, par exemple, à :
-tester l'existence, si absent renvoie 0 et quitte la fonction
-supprimer
-tester l'existence, renvoie 1 si absent et -1 si présent.
Donc bien plus d'informations renvoyées, mais plus lent.


Qu'en pensez vous ?

 

De MadMatt le 02/01/2007 à 19:25


Pour ce que tu propose je suis d'accord, mais pourquoi séparer le cas 0 et -1. Certaines fonctions peuvent travailler à moitié, c'est flou comme notion, car ça ne précise pas non plus l'erreur.
dans l'exemple du fichier, DeleteFile renvoie (selon la msdn et d'autres sites d'api) :
If the function succeeds, the return value is nonzero.
If the function fails, the return value is 0 (zero). To get extended error information, call GetLastError.

Pas besoin de tester l'existence du fichier. Juste si DeleteFile renvoie 0, on renvoie -1, sinon on renvoie 1.

 

De sebdraluorg le 02/01/2007 à 19:25


eh wai faut mettre un systeme d'erreur un place le -1 est pas mal sauf que CBool(-1) = true
Sinon on peut recuperer une description depuis Err.GetLastDllError ce qui donnerait

KillFile = DeleteFile(FullPath)
If KillFile = 0 Then MsgBox GetError(Err.LastDllError)

PS: Je vais deposer le code de GetError

 

De MadMatt le 02/01/2007 à 19:28


Ah je savais pas que CBool(-1)=True
Au pire on s'en fout, si on prend comme code d'erreur -1, l'utilisateur doit le savoir... Ou alors on utilise des booléens.

 

De violent_ken le 02/01/2007 à 19:35


Oui, True <==> -1, mais -1 est utilisé par un grand nombre d'API.


"Juste si DeleteFile renvoie 0, on renvoie -1, sinon on renvoie 1" ==> C'est vrai.
Différencier 0 de -1 permet, dans ce cas précis, de renseigner l'utilisateur sur le fait que le fichier n'a pas pu être supprimé (-1) ou bien que le fichier n'existait deja pas (0).
Mais là, le code ACCESS_DENIED apparaitra sans doute avec GetLastDllError.

 

De sebdraluorg le 02/01/2007 à 19:53


Eh oui sinon un Err.LastDllError renvoi 0 si Error_Success
donc on peut faire killFile = Err.LastDllError

L'utilisateur recevra 0 si reussi ou un hError si erreur et il pourra ensuite faire GetError pour avoir la description.
Sinon je ne vois pas comment il pourra recuperer la nature de l'erreur...

 

De violent_ken le 02/01/2007 à 19:56


Oui, çà marche très bien, mais le seul problème c'est que les retours de fonctions ne seront pas unifiés dans le projet.
Pour récupérer le code de l'erreur, on peut envisager de créer une property LastError.


Après, c'est des choix à faire ;)

 

De sebdraluorg le 02/01/2007 à 20:06


Eh tu veux dire quoi par ne seront pas unifiés ?

Cette methode est applicable a tous les appels d'api normalement.

La propriete LastError c'est bien, mais si tu fais killfile fichier1 puis killfile fichier2 et que tu as eu une erreur sur KillFile fichier1 tu ne le saura pas. c'est pour ca que je voulais renvoyer directement le code d'erreur.

Apres comme tu dis c'est une question de choix, moi je vous suis si vous preferez les 1, 0 et -1

++

 

De violent_ken le 02/01/2007 à 20:08


"La propriete LastError c'est bien, mais si tu fais killfile fichier1 puis killfile fichier2 et que tu as eu une erreur sur KillFile fichier1 tu ne le saura pas. c'est pour ca que je voulais renvoyer directement le code d'erreur." ==> Ah oui, c'est là le dilemne !



Pas unifié ==> "recevra 0 si reussi" ==> ce résultat n'est pas applicable partout (exemple, une fonction renvoyant un handle renverra 0 si échec, et n>0 si réussi)

 

De sebdraluorg le 02/01/2007 à 20:27


Yep en effet c'est pas applicable dans ces cas la...

Sinon on pourrait ajouter un "Optional ByRef hError" a nos fonctions qui renverrait les hError et la fonction en elle meme renverrai 1, 0 ou -1

 

De violent_ken le 02/01/2007 à 20:41


Ah oui, çà c'est une solution

 

De MadMatt le 03/01/2007 à 14:17


Dsl de pas avoir pu participer au débat hier soir ^^
au niveau d'un parametre supplémentaire dans toutes les fonctions, c'est pas mal de boulot, ça complique les déclarations, pour l'utilisateur ça peut lui compliquer le truc plus qu'autre chose.
Perso je pense que le coup d'avoir une propriété LastError peut etre pas mal, en regardant bien les api font la meme chose après tout. On peut faire une classe LastError par exemple, et elle a une propriété Handle et une propriété ToString qui renvoie l'erreur convertie en texte, ça fait beaucoup moins lourd et plus transparent.
Et après nos fonctions renvoie 1 0 ou -1

parce que pour le coup du dilemne KillFile fichier1 et KillFile fichier2, KillFile fichier1 va renvoyer qu'il a rencontré une erreur et après à l'utilisateur d'appeler "LastError" avant de faire KillFile fichier2 ??

 

De MadMatt le 03/01/2007 à 14:20


parce qu'en plus, je viens de voir dans ta source seb, au niveau des hError y'a 2 types : les classiques et les hError des api NtQuery
Avec une classe, la fonction peut préciser à la classe le type de l'erreur (par une propriété ErrorType par exemple) pour retrouver la description.

 

De sebdraluorg le 03/01/2007 à 16:16


Eh wai y a 2 type de hError, mais la fonction aurait convertit l'erreur en hError "standard" avant de la renvoyer...

M'enfin oui c'est vrai que c'est un peu lourd d'avoir un parametre supplementaire a chaque fonction, bien qu'il aurait ete en Optional.

La class LastError me va aussi, on peut partir la dessus si tout le monde est ok

++

 

Ajouter un commentaire


Vous devez être connecté pour pouvoir poster un commentaire.

 
 

Valid HTML 4.01 Transitional Valid CSS

Site web de Vb System Library version 1.3
Developpement et design réalisé par : Matthieu Napoli (MadMatt)
© 2007 Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
Temps d'execution de la page : 0.033 s
www.mnapoli.fr