Page 1 sur 1

[Windows] FileSize like

Publié : mar. 29/nov./2022 8:49
par boddhi
Bonjour,

A toutes fins utiles,
Sous Windows, lorsque la longueur d'un nom d'arborescence, de dossier ou de fichier dépasse les 259 caractères, la commande FileSize(), même utilisée conjointement avec le préfixe "\\?\", ne fonctionne pas correctement.
Avoir défini la clé de registre "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled" à 1 ne change en rien cet état de fait.

Ci-dessous, donc, un FileSize-like qui reprend les mêmes principes que l'original à savoir une valeur de retour :
  • -2 : Si le fichier passé en paramètre est en réalité un dossier
  • -1 : Si le fichier ou dossier passé en paramètre n'existe pas
  • >= 0 : La taille du fichier
et
  • -3 : Dans l'éventualité d'une erreur non prévue (en théorie, cela ne devrait pas se produire)

Code : Tout sélectionner

; Fonction utilisable uniquement à partir de Windows 10 build 14352
; Par ailleurs, si absente, la clé "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled", avec pour valeur 1, 
; doit être créée dans la base de registre. Un redémarrage Windows est alors nécessaire


Procedure.i FileSize_Like(ArgNomFichier.s)
  ; Retourne -3 si anomalie non prévue
  ; Retourne -2 si ArgNomFichier est un répertoire
  ; retourne -1 si le fichier/répertoire est inexistant
  ; sinon retourne la taille du fichier
  Protected.i IdFichier,TailleHauteFichier,TailleBasseFichier,ValeurRetour
  
  If Left(ArgNomFichier,4)<>"\\?\":ArgNomFichier="\\?\"+ArgNomFichier:EndIf
  IdFichier=CreateFile_(@ArgNomFichier,#GENERIC_READ,#FILE_SHARE_READ,0,#OPEN_EXISTING,#FILE_FLAG_BACKUP_SEMANTICS,0)
  If IdFichier=#INVALID_HANDLE_VALUE
    ; Debug "  Dossier/Fichier inexistant"
    CloseHandle_(IdFichier)
    ProcedureReturn IdFichier
  Else
    CloseHandle_(IdFichier)
    IdFichier=CreateFile_(@ArgNomFichier,#GENERIC_READ,#FILE_SHARE_READ|#FILE_SHARE_DELETE,0,#OPEN_EXISTING,#FILE_ATTRIBUTE_NORMAL,0)
    If IdFichier=#INVALID_HANDLE_VALUE
      If GetLastError_()=0
        ; Debug "  "+ArgNomFichier+" est un fichier"
      Else
        If GetLastError_()=#ERROR_PATH_NOT_FOUND
          ; Debug "  "+ArgNomFichier+" est un répertoire"
          ValeurRetour=-2
        Else
          Debug "  Code erreur "+GetLastError_()+" à gérer par l'utilisateur"
          ValeurRetour=IdFichier
        EndIf
      EndIf
    Else
      TailleBasseFichier=GetFileSize_(IdFichier,TailleHauteFichier)
      If TailleBasseFichier=#INVALID_FILE_SIZE And TailleHauteFichier=#Null
        ValeurRetour=-3
        Debug "  Code erreur "+GetLastError_()+" à gérer par l'utilisateur"
      Else
        ValeurRetour=TailleBasseFichier
      EndIf
    EndIf
    CloseHandle_(IdFichier)
    ProcedureReturn ValeurRetour
  EndIf
EndProcedure

Pour le test, créez, par exemple, via l'explorateur, l'arborescence suivante :
"C:\123456789-123456789-123456789-123456789-12456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-ABCDEFGHI\123456789-123456789-123456789-123456789-12456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-ABCDEFGHI\"

puis lancez

Code : Tout sélectionner

Fichier.s="C:\123456789-123456789-123456789-123456789-12456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-ABCDEFGHI\123456789-123456789-123456789-123456789-12456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-ABCDEFGHI\"
Debug Len(Fichier)
Debug FileSize(Fichier)
Debug FileSize("\\?\"+Fichier)
Debug FileSize_Like(Fichier)
Vous pouvez ensuite faire de même avec des fichiers créés dans cette arborescence.

Voilà.

[Edition 18.01.23 - Ajout, dans le code source, d'un commentaire lié à la version de Windows requise]

Re: [Windows] FileSize like

Publié : jeu. 15/déc./2022 20:52
par Ollivier
Si je comprends bien, on peut créer un fichier officiellement vide qui, en réalité est un binaire en base64 stocké dans le titre.

Re: [Windows] FileSize like

Publié : lun. 19/déc./2022 0:36
par boddhi
:oops: Pardon, pas tout bien compris le propos... :)

Dans le doute, j'itère : Le but de cette astuce est de pouvoir obtenir la taille d'un fichier (ou, à défaut, déterminer son inexistance ou si on a affaire à un dossier) dont le nom complet (arborescence + nom + extension) est constitué de plus de 259 caractères. Ce que ne gère pas très bien la fonction native PB FileSize(). Les valeurs de retour sont identiques pour garder l'esprit de la commande originelle.

Dans mon exemple, la valeur de la variable Fichier correspond, certes, en réalité à un dossier dont le nom a une longueur de 401 caractères (les séquences '123456789-' qui le constitue ne sont là que pour en faciliter la composition et la lecture) mais il aurait très bien pu s'agir d'un fichier.
Et si j'ai, effectivement, utilisé une variable nommée 'Fichier' passée en paramètre à la fonction FileSize_Like(), là encore, c'était pour garder l'esprit de FileSize() qui a pour premier argument FileName quand bien même il s'agirait d'un répertoire...

Espérant avoir été (plus) clair ! :wink:

Re: [Windows] FileSize like

Publié : mar. 17/janv./2023 11:47
par Kwai chang caine
Merci de ton partage BODDHI 8)
Perso ce que je n'arrive pas à faire c'est créer le fichier de plus de 240 caractères (Sans le "C:\SPTemp\" évidemment), car l'explorateur tronque le nom et m’empêche par la suite de rajouter d'autres caractères :oops:
J'ai pu créer que ça
C:\SPTemp\123456789-123456789-123456789-123456789-12456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-ABCDEFGHI123456789-123456789-123456789-123456789
Du coup la réponse est bonne avec FileSize()
247
2114
2114
2114

Re: [Windows] FileSize like

Publié : mer. 18/janv./2023 7:41
par boddhi
@KCC

J'ai oublié de préciser que cette fonction n'est utilisable qu'à partir de Windows 10 build 14352, version à partir de laquelle MS a modifié le nombre de caractères autorisées (260 avant contre 32767 depuis).
Néanmoins, pour que cela soit opérationnel (ça ne l'est hélas par défaut, tout du moins au moment où est sortie cette build), il convient de créer dans la base de registre la clé "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled" avec pour valeur 1 (un redémarrage de Windows est ensuite nécessaire !).

Si tu vérifies ces deux conditions, tu crées par exemple une arborescence de type "C:\Sous-dossier 1\Sous_dossier 2\...\Sous-dossier 20\" avec l'explorateur (Note : Pas la peine de tenter avec CreateFile(), même avec une fonction récursive, ça finit par tronquer le nom de répertoires !) puis tu testes la fonction...

Il est à noter que nombres d'applications, même récentes, ne tiennent pas encore compte de cette évolution !

Ci-dessous, un test :

Code : Tout sélectionner

Fichier.s="D:\Sous dossier 1\Sous dossier 2\Sous dossier 3\Sous dossier 4\Sous dossier 5\Sous dossier 6\Sous dossier 7\Sous dossier 8\Sous dossier 9\Sous dossier 10\Sous dossier 11\Sous dossier 12\Sous dossier 13\Sous dossier 14\Sous dossier 15\Sous dossier 16\Sous dossier 17\Sous dossier 18\Sous dossier 19\Sous dossier 20\"
Debug "Fichier : "+Fichier
Debug "Longueur nom fichier : "+Len(Fichier)
Debug "Résultat FileSize() : "+FileSize(Fichier)
Debug "Résultat FileSize() avec '\\?\' : "+FileSize("\\?\"+Fichier)
Debug "Résultat FileSize_Like() : "+FileSize_Like(Fichier)
Debug "--------------------------"
Fichier+"Fichier test.tmp"
Debug "Fichier : "+Fichier
Debug "Longueur nom fichier : "+Len(Fichier)
Debug "Résultat FileSize() : "+FileSize(Fichier)
Debug "Résultat FileSize() avec '\\?\' : "+FileSize("\\?\"+Fichier)
Debug "Résultat FileSize_Like() : "+FileSize_Like(Fichier)
Le résultat :
Image

Re: [Windows] FileSize like

Publié : jeu. 26/janv./2023 17:17
par Kwai chang caine
Merci beaucoup de ton explication :D

Justement comme j'avais une arborescence monstrueuse dans mes DD, il y a plus de 10 ans j'ai remplacé tous les titres de dossiers par une seule lettre
Du coups, je n'ai plus eu de problèmes de nom de fichier trop long depuis cette période 8)

Je ne sais pas si tu imagines mes chemins de fichiers de tous mes DD sont du style :
C:\A\B\A\B\C\D\F\G\A\A\Ma facture EDF.jpg
Ma femme est folle, elle se dit que quand je vais mourir....elle aura plus vite fait de réclamer tous mes papiers officiels aux organismes que de les retrouver dans mes DD d'archives :lol:
Bon..faut dire qu'elle y connait encore moins que moi (mais si c'est possible :mrgreen: ), elle connait pas les recherches indexées, et logiciels d'aide au recherches.

Le seul blême...en les utilisant tous les jours, je commençais à me rappeler de la signification de chaque dossier, mais c'est qu'en vieillissant...comme dirait YODA, je suis en train de désapprendre tout ce que j'ai appris :lol:

Alors dernièrement, je me suis un peu inquiété à ce sujet, et je me suis dit que peut être BILOU il avait prévu de pouvoir mettre des infos dans les attributs NTFS des dossiers, comme on peut le faire dans les fichiers, mais quedal, j'ai rien trouvé :cry:
A part l’icône et le titre ou un fichier infos dedans comme le fait actuellement windows, on peut pas rajouter grand chose comme infos à un dossier...une nouvelle idée de rajouter du texte dans l’icône m'est venue...mais bon..c'est une autre histoire :wink:

Et aussi j'en profite pour te remercier pour le partage de tes nombreux codes tu es drôlement prolifique 8)