2017-07-08 4 views
0

J'ai le code suivant qui renvoie parfois une erreur lors de la tentative de création d'un nouveau répertoire. Parfois, lorsque ce répertoire n'existe pas, il génère une erreur et ne crée pas le répertoire. J'aimerais savoir pourquoi?CreateDir génère une exception dans QB64

DECLARE DYNAMIC LIBRARY "kernel32" 
    FUNCTION CreateDirectoryA% (F$, X$) 
    FUNCTION GetLastError&() 
END DECLARE 
F$ = "TEMPX" + CHR$(0) ' new directory to create 
x = CreateDirectoryA(F$, CHR$(0)) 
IF x = 0 THEN 
    IF GetLastError = &H3E6 THEN 
     PRINT "Invalid access to memory location." 
    END IF 
END IF 

Ce code a été écrit en QB64.

+0

Quand j'ai dit "parfois" je voulais dire que parfois cela ne produit pas d'erreur. – eoredson

Répondre

0

Puis je suis tombé sur un problème créant des sous-répertoires dans un chemin, donc j'écrit ceci:

DECLARE DYNAMIC LIBRARY "kernel32" 
    FUNCTION CreateDirectoryA% (F$, BYVAL X&&) 
    FUNCTION GetLastError&() 
END DECLARE 
DO ' get directory 
    PRINT "Dir";: INPUT Directory$ 
    IF Directory$ = "" THEN END 
    GOSUB CreateDir 
LOOP 
END 
CreateDir: 
' construct path 
Directory$ = RTRIM$(Directory$) 
IF RIGHT$(Directory$, 1) <> "\" THEN 
    Directory$ = Directory$ + "\" 
END IF 
' create path 
x = 0 
Next.Dir = INSTR(Directory$, "\") 
DO 
    IF Next.Dir = False THEN 
     EXIT DO 
    END IF 
    SubDir$ = LEFT$(Directory$, Next.Dir - 1) ' \tempx\t1\t2\t3\ 
    Next.Dir = INSTR(Next.Dir + 1, Directory$, "\") 
    ' make directory name 
    IF LEN(SubDir$) THEN 
     ' create directory 
     f$ = SubDir$ + CHR$(0) 
     x = CreateDirectoryA(f$, 0) 
     ' check error 
     IF x = 0 THEN 
      IF GetLastError& = &HB7 THEN ' ignore already exists 
       ' nul 
      ELSE 
       EXIT DO 
      END IF 
     END IF 
    END IF 
LOOP 
IF x = 0 THEN 
    PRINT "Error x"; HEX$(GetLastError&) 
ELSE 
    PRINT "Directory created." 
END IF 
RETURN 

De cette façon, si vous spécifiez un chemin qui n'existe pas, il va créer l'ensemble de chemin. Par exemple, \ Temp \ t1 \ t2 \ t3 si \ Temp n'existe pas.

+0

Parce que si vous ne le faites pas alors vous obtenez une erreur 0x3 qui est un "Le système ne peut pas trouver le chemin spécifié." – eoredson

0

Ce code Impose la création d'un répertoire lorsque l'exception x3E6 arrive mais n'explique pourquoi l'erreur se produit en premier lieu:

DECLARE DYNAMIC LIBRARY "kernel32" 
    FUNCTION CreateDirectoryA% (F$, X$) 
    FUNCTION GetLastError&() 
END DECLARE 
DO 
    F$ = "TEMPX" + CHR$(0) ' new directory to create 
    x = CreateDirectoryA(F$, CHR$(0)) 
    IF x THEN ' successful create 
     EXIT DO 
    END IF 
    IF x = 0 THEN 
     REM Test for Invalid access to memory location. 
     IF GetLastError = &H3E6 THEN 
      _DELAY .2 
     ELSE 
      EXIT DO 
     END IF 
    END IF 
LOOP 
+0

Odd. Je pense que 'lpSecurityAttributes' (' X $' dans votre déclaration) serait quelque chose comme '_OFFSET' (' X% & ') plutôt qu'une chaîne. 'CHR $ (0)' implique que vous avez une chaîne contenant un seul octet avec la valeur 0, donc je passerais '0% &' à la fonction, résultant en un pointeur 'NULL'. Le 'CHR $ (0)' pourrait être la cause de votre problème "parfois". Là encore, je n'ai pas utilisé Windows depuis un moment, alors peut-être que je me trompe. Je suis surpris qu'il n'y ait pas encore de ressource qui mette en correspondance différents types de données de l'API C/Windows avec les types QB64 ... –

+0

Toutes les chaînes passées aux bibliothèques Windows sont nécessairement terminées par un caractère nul. La valeur null dans le second paramètre est requise. Le premier paramètre déclare un pointeur sur la fonction comme il se doit. – eoredson

+0

Je fais référence à un pointeur NULL, pas à une chaîne terminée par un caractère nul. 'lpSecurityAttributes' est un pointeur vers une structure, pas une chaîne, mais je vous ai déjà vu publier ce genre de choses, alors peut-être que vous connaissez quelque chose que je ne connais pas. Après tout, je ne travaille plus avec QB64, donc tout ce que je dis peut être basé sur des souvenirs rouillés. : P –

1

Qu'est-ce que vous passez comme paramètre lpSecurityAttributes de CreateDirectoryA est une chaîne de longueur 0; les chaînes ont toujours des adresses mémoire, ce qui signifie que vous passez un pointeur non nul. Cela est interprété par CreateDirectoryA comme un pointeur vers un SECURITY_ATTRIBUTES structure avec son premier octet défini sur 0. Les autres octets de la structure sont de la mémoire que vous n'avez pas initialisée, ce qui signifie que le premier champ nLength de la structure peut être quelque chose comme 0xFFFFFF00, qui est 4294967040 — une taille invalide. Le champ lpSecurityDescriptor de cette structure est vraisemblablement rempli d'octets (éventuellement accessibles par votre programme, mais peut-être pas), ce qui peut être à l'origine du problème.

Vous pouvez facilement y remédier:

' X%& may also be written X AS _OFFSET. 
FUNCTION CreateDirectoryA% (F$, BYVAL X%&) 

... 

x = CreateDirectoryA(F$, 0) 

Il en résulte le passage d'un pointeur NULL correctement. Le mot-clé BYVAL est nécessaire, sinon vous passez un pointeur à la valeur _OFFSET (parce que tout dans QB64 est passé par pointeur sauf si vous utilisez le mot-clé BYVAL, les chaînes et les types définis par l'utilisateur ne peuvent pas être passés BYVAL).

+0

Merci! Cela a peut-être résolu le problème. Pouces vers le haut. – eoredson

+0

Et la fonction CreateDirectory appelle la structure SECURITY_ATTRIBUTES. Et la structure SECURITY_ATTRIBUTES pointe vers la structure SECURITY_DESCRIPTOR. Et le... – eoredson

+0

Un descripteur de sécurité comprend: un identificateur de sécurité d'emploi (SID) Un groupe primaire SID d'une liste de contrôle d'accès discrétionnaire (DACL) d'une liste de contrôle d'accès au système (SACL) – eoredson