Utilisation de FindFirstFileEx [Résolu]

Messages postés
1212
Date d'inscription
dimanche 20 avril 2003
Dernière intervention
4 juin 2016
- - Dernière réponse :  Utilisateur anonyme - 18 déc. 2012 à 14:06
Bonjour à tous,

J'ai besoin de texter l'existence (ou non) d'un sous-répertoire, c'est à dire savoir si AU MOINS UN sous-répertoire existe ou non dans un dossier donné.

Pour ça l'API FindFirstFile n'est pas très efficiente car elle ne fait pas le distingo a priori sur dossier/fichier. Sachant que le scan se fait dans un ordre aléatoire, je ne voudrais pas être obligé de scanner X fichiers avant de découvrir qu'il n'y a pas de sous-dossiers.

Par contre j'ai découvert l'API FindFirstFileEx, mais celle-ci utilise un Enum en C (que j'ai) mais sans valeur:
typedef enum _FINDEX_SEARCH_OPS {
    FindExSearchNameMatch,
    FindExSearchLimitToDirectories,
    FindExSearchLimitToDevices,
    FindExSearchMaxSearchOp
} FINDEX_SEARCH_OPS


Je crois me souvenir qu'en l'absence de valeur pour chaque item VB lui attribue un long commençant à 0.

Ma question, quelqu'un a t'il déjà utiliser cette API en VB6 ou possède quelques notions de transposition d'une telle énumération de C vers VB. Cela me rendrait bigrement service.

Merci d'avance.


Calade
Afficher la suite 

Votre réponse

20/22 réponses

Meilleure réponse
Messages postés
1212
Date d'inscription
dimanche 20 avril 2003
Dernière intervention
4 juin 2016
3
Merci
Bonjour,

et désolé pour le délai.
Vous avez tous raison:
@Active: Je suis d'accord que Dir() et/ou FSO rempliraient le même office, mais à quel prix.

@ucFoutu: Ta solution est la 1ère à laquelle j'avais pensé, mais comme le dit Active, il faut x lignes de code et une boucle pour un simple test d'existence d'un dossier. Quant à FSO, cela alourdit d'autant l'exe final.

D'où mon intéret pour FindFirstFileEx. Si quelqu'un connait la réponse...

PS: Je mets le poste en "résolu" pour les futurs chercheurs, mais si j'obtiens la réponse, ce serait la cerise sur le gâteau.


Calade

Merci Calade 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 97 internautes ce mois-ci

Commenter la réponse de Calade
0
Merci
Bonjour,

Le second paramètre de la fonction retourne une structure de type WIN32_FIND_DATA.
Le premier paramètre de cette structure représentent les attributs du premier élément trouvé.
Et l'on peut lire ceci :
FILE_ATTRIBUTE_DIRECTORY  16 (0x10) The handle that identifies a directory.
Commenter la réponse de Utilisateur anonyme
0
Merci
Je parlais de FindFirstFile donc et non pas de FindFirstFileEx.
Commenter la réponse de Utilisateur anonyme
0
Merci
Bonjour,
J'ai besoin de texter l'existence (ou non) d'un sous-répertoire, c'est à dire savoir si AU MOINS UN sous-répertoire existe ou non dans un dossier donné.

Pourquoi se compliquer la vie...
Dim FSO: Set FSO = CreateObject("Scripting.FileSystemObject")
Dim ObjRep: Set ObjRep = FSO.GetFolder("c:\windows") 'dossier
Dim ObjSubRep: Set ObjSubRep = ObjRep.SubFolders 'sous-dossiers
MsgBox "Vous avez dans le dossier c:\windows\ " & ObjSubRep.Count & " dossiers !"



Cordialement


CF2i - Guadeloupe
Ingénierie Informatique
Commenter la réponse de Utilisateur anonyme
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Contributeur
Dernière intervention
11 avril 2018
0
Merci
Bonjour à tous,
nil besoin :
- ni de faire appel à une fonction de l'Api de Windows
- ni d'alourdir avec FSO
pour si peu, alors que VB6 possède la fonction Dir, suffisante, rapide et efficace . ===>> Un exemple bâclé ===>>

dossier = "d:\abcdefg"
 If Dir(dossier, vbDirectory) <> "" Then MsgBox dossier & " existe" Else MsgBox "n' existe pas": Exit Sub
 sousdossier = Dir(dossier & "", vbDirectory)
 Do While sousdossier <> ""
    If sousdossier <> "." And sousdossier <> ".." Then
        If (GetAttr(dossier & "" & sousdossier) And vbDirectory) = vbDirectory Then
            toto = toto & vbCrLf & sousdossier
        End If
    End If
    sousdossier = Dir
 Loop
 If toto "" Then toto vbCrLf & "aucun"
 MsgBox dossier & " contient le(s) sous-dossier(s)" & toto


________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviendrai que si nécessité de la compléter.
Commenter la réponse de ucfoutu
0
Merci
Exact... j'avais oublié le Dir...


Cordialement


CF2i - Guadeloupe
Ingénierie Informatique
Commenter la réponse de Utilisateur anonyme
0
Merci
Et je m'abstiendrais de répondre sur le forum vb6 à l'avenir.
Mais tout de même, 12 lignes de code pour tester l'existence d'un sous-dossier me laisse rêveur...
Commenter la réponse de Utilisateur anonyme
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Contributeur
Dernière intervention
11 avril 2018
0
Merci
Salut, Banana32,
où vois-tu la nécessité de 12 lignes de code ? J'ai voulu mettre ici un exemple qui allait au-delà, c'est tout ! Il suffit d'y puiser ce dont on a besoin et de laisser tout tout le reste


________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviendrai que si nécessité de la compléter.
Commenter la réponse de ucfoutu
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Contributeur
Dernière intervention
11 avril 2018
0
Merci
Regarde, maintenant (et je vais encore au-delà de ce qui est demandé par Calade, puisque je compte le nombre des sous-dossiers) ===>>>
Private Function contient_x_sousdossiers(dossier As String) As Integer
  sousdossier = Dir(dossier, vbDirectory)
  Do While sousdossier <> ""
    If sousdossier <> "." And sousdossier <> ".." Then contient_x_sousdossiers = contient_x_sousdossiers + 1
    sousdossier = Dir
 Loop
End Function

Appelable ainsi :
MsgBox contient_x_sousdossiers("d:\abcdefg")


________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviendrai que si nécessité de la compléter.
Commenter la réponse de ucfoutu
0
Merci
Re ucfoutu,

je vais encore au-delà de ce qui est demandé par Calade
Merci pour lui

Ca fait encore 6 lignes de code.
On a bien fait de mettre vb6 au rebut finalement.

Allez, si tu y arrives en 1 ligne (comme en .NET) je retirerai ma dernière phrase ... ou pas!
Commenter la réponse de Utilisateur anonyme
0
Merci
Bonjour,
Moi je reste à 3 lignes minimum, avec le Dir, il faut un Do/Loop au minimum ... mais je cherche encore...


Cordialement


CF2i - Guadeloupe
Ingénierie Informatique
Commenter la réponse de Utilisateur anonyme
Messages postés
18039
Date d'inscription
lundi 7 décembre 2009
Statut
Contributeur
Dernière intervention
11 avril 2018
0
Merci
@ucFoutu: Ta solution est la 1ère à laquelle j'avais pensé, mais comme le dit Active, il faut x lignes de code et une boucle pour un simple test d'existence d'un dossier. Quant à FSO, cela alourdit d'autant l'exe final

- Si ce n'est que pour vérifier l'existence d'un dossier, une seule ligne de code suffit !
If Dir(dossier, vbDirectory) <> ""

- je ne vois pas (mais alors pas du tout) en quoi (bien au contraire) passer par FindFirstFileEx allègerait le code !
________________________
Réponse exacte ? => "REPONSE ACCEPTEE" facilitera les recherches.
Pas d'aide en ligne installée ? => ne comptez pas sur moi pour simplement répéter son contenu. Je n'interviendrai que si nécessité de la compléter.
Commenter la réponse de ucfoutu
0
Merci
Bonjour Uc,

Il faut obligatoirement faire une boucle;
Le dir prend en compte (comme sous dos) les dossiers "." et ".." et... bizarrement il liste tout les fichiers également, malgré le vbDirectory comme filtre.

Il faut en suite vérifier un par un pour savoir si c'est un fichier ou un dossier et s'il est différent de "." et ".."
C'est la méthode chez msdn...

Par contre avec un contrôle DirListBox il n'y a aucun problème, mais, il faut un contrôle supplémentaire


Cordialement


CF2i - Guadeloupe
Ingénierie Informatique
Commenter la réponse de Utilisateur anonyme
0
Merci
On pourrait l'imaginer comme ça:

Dim Ls As Control

Private Sub Form_Load()
Set Ls = Controls.Add("VB.DirListBox", "Dirextory1")
End Sub

Private Sub Command1_Click()
Ls.Path = "c:\tempo"
Ls.Refresh
If Ls.ListCount > 0 Then
   MsgBox "Vous avez un (des) dossier(s)"
Else
   MsgBox "Vous n'avez aucun dossier"
End If
End Sub



Cordialement


CF2i - Guadeloupe
Ingénierie Informatique
Commenter la réponse de Utilisateur anonyme
Messages postés
1212
Date d'inscription
dimanche 20 avril 2003
Dernière intervention
4 juin 2016
0
Merci
@ucFoutu,

- Si ce n'est que pour vérifier l'existence d'un dossier, une seule ligne de code suffit !


Oui (et encore), mais à condition de connaître son nom, ce qui dans mon cas, n'est pas vrai. Je veux savoir s'il y a ou non un ou des dossiers où s'il est vide. Le nom m'importe peu et de toutes façons je ne le connais pas.

En tout cas merci pour tout.


Calade
Commenter la réponse de Calade
Messages postés
1212
Date d'inscription
dimanche 20 avril 2003
Dernière intervention
4 juin 2016
0
Merci
Ayant posé la même question sur un autre forum (je sais, je suis têtu), j'ai eu l'assurance que les enum fonctionnaient à l'identique en C/C++ et VB6 à savoir une numérotation automatique à partir de 0 (le tout en long évidemment).

J'ai donc fait des essais concluants et je poste ici un squelette pour ceux qui seraient intéressés:
' Déclaration de l'API
Public Declare Function FindFirstFileEx Lib "kernel32.dll" Alias "FindFirstFileExA" (ByVal lpFileName As String, ByVal fInfoLevelId As FINDEX_INFO_LEVELS, lpFindFileData As Any, ByVal fSearchOp As FINDEX_SEARCH_OPS, lpSearchFilter As Any, ByVal dwAdditionalFlags As Long) As Long

'Les enums transposés du C et numérotés pour plus de lisibilité

Public Enum FINDEX_INFO_LEVELS
  FindExInfoStandard = 0&
  FindExInfoBasic = 1&                                               ' NOT SUPPORTED before W7
  FindExInfoMaxInfoLevel = 2&
End Enum
#If False Then
   Private FindExInfoStandard, FindExInfoBasic, FindExInfoMaxInfoLevel
#End If

Public Enum FINDEX_SEARCH_OPS
    FindExSearchNameMatch = 0&
    FindExSearchLimitToDirectories = 1&
    FindExSearchLimitToDevices = 2&
    FindExSearchMaxSearchOp = 3&
End Enum
#If False Then
   Private FindExSearchNameMatch, FindExSearchLimitToDirectories, FindExSearchLimitToDevices, FindExSearchMaxSearchOp
#End If

' Ma fonction d'appel
Public Function BH_IsAnyFolder(ByVal FolderName As String, Optional ByVal Filter As String = "*") As Boolean
   Dim W32_F_D_Buffer As WIN32_FIND_DATA, lngHandle As Long

   FolderName = BH_AddBackSlash2Folder(FolderName) & Filter
   lngHandle = FindFirstFileEx(FolderName, FindExInfoStandard, W32_F_D_Buffer, FindExSearchLimitToDirectories, 0&, 0&)
if lngHandle > 0 then
   BH_IsAnyFolder=true
   call FindClose(lngHandle)
End Function


Par contre, tout comme le Dir(), elle renvoie les fameux dossiers fantômes "." et "..", donc à tenir compte dans ma fonction ce que je n'ai pas (encore fait). On y gagne éventuellement le distingo entre majuscules/minuscules (le dernier paramètre doit être égal à 1).

Bien lire le MSDN avant utilisation car certaines options ne fonctionnent pas avant W7. Perso' je suis encore sous XP SP3.

Calade
Commenter la réponse de Calade
0
Merci
call FindClose(lngHandle)

Il semble qu'il nous manque un bout de code (une dizaine de lignes de plus ? )
Commenter la réponse de Utilisateur anonyme
Messages postés
1212
Date d'inscription
dimanche 20 avril 2003
Dernière intervention
4 juin 2016
0
Merci
Comme je l'ai précisé à la fin de mon message.


Calade
Commenter la réponse de Calade
0
Merci
Allez...
En une seule ligne :

Set Ls Controls.Add("VB.DirListBox", "Dirextory1"): Ls.Path "c:\tempo": Ls.Refresh: MsgBox "Dossiers : " & Ls.ListCount: Controls.Remove Ls


Cordialement


CF2i - Guadeloupe
Ingénierie Informatique
Commenter la réponse de Utilisateur anonyme
Messages postés
1212
Date d'inscription
dimanche 20 avril 2003
Dernière intervention
4 juin 2016
0
Merci
OK mais cela fait ajouter un contrôle peut-être inutile.
Pas vraiment léger comme solution.

A mon avis il n'y a que deux solutions vraiment efficientes, celle d'ucFoutu en pure VB avec le Dir() ou l'API ci-dessus.

Encore faudrait-il tester réellement pour connaître la + rapide, mais quand on ne parcourt le dossier pour, au pire, 3 dossiers, la différence éventuelle de durée n'est pas significative sur les PC modernes.

Calade
Commenter la réponse de Calade

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.