CreateDirectory -> CreateFile

Windows specific forum
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

CreateDirectory -> CreateFile

Post by IdeasVacuum »

PB5.62 x86 Win7 x64

Something I have not seen before - Create a new file path (4 to 6 folders), all returning success, then create a file with that path - first attempt fails.

Workaround:

Code: Select all

iCreate = CreateFile(#FileIO, sFileFullPath, #PB_UTF8) : CloseFile(#FileIO)
iCreate = CreateFile(#FileIO, sFileFullPath, #PB_UTF8)
Anyone else seen this?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: CreateDirectory -> CreateFile

Post by RSBasic »

Do you mean like this?

Code: Select all

EnableExplicit

#FileIO = 1

Define sFileFullPath.s = "D:\Folder1\Folder2\Folder3\Folder4\MyFile.txt"

Debug CreateDirectory("D:\Folder1\")
Debug CreateDirectory("D:\Folder1\Folder2\")
Debug CreateDirectory("D:\Folder1\Folder2\Folder3\")
Debug CreateDirectory("D:\Folder1\Folder2\Folder3\Folder4\")
Debug CreateFile(#FileIO, sFileFullPath, #PB_UTF8)
CloseFile(#FileIO)
I can't confirm that.

Have you tried it yet?

Code: Select all

SetCurrentDirectory(GetPathPart(ProgramFilename()))
It could be that your file is created in the virtual directory. Check this: %localappdata%\VirtualStore\

And have you tested without anti-virus software?
Image
Image
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: CreateDirectory -> CreateFile

Post by IdeasVacuum »

Hello RSBasic

Thanks for your input.

The path is created correctly, that can be observed. It's not however starting at root, it is a temporary path in appdata (FOLDERID_RoamingAppData) constructed to ensure a subsequent zip file creation holds the correct paths, and the files are created at run time (always different). I would have the path pre-created by the installer usually, but in this case some of the folder names are dynamic (user project dependent).

So, tested this morning and without any code changes other than commenting out the work-around (AV still on too), I cannot get it to fail!

Going to test it on some other PCs/Windows OS and see what happens there. It's almost as though the path is created a fraction too late so the file creation fails - but if I add a Delay(), that theory is trashed.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: CreateDirectory -> CreateFile

Post by RSBasic »

IdeasVacuum wrote:It's almost as though the path is created a fraction too late so the file creation fails
Hm, you can try this:

Code: Select all

EnableExplicit

Procedure.s GetLastError()
  Protected ErrorBufferPointer.L
  Protected ErrorCode.L
  Protected ErrorText.S
  Protected ferr
  
  ErrorCode = GetLastError_()
  ferr = FormatMessage_(#FORMAT_MESSAGE_ALLOCATE_BUFFER | #FORMAT_MESSAGE_FROM_SYSTEM, 0 , ErrorCode, GetUserDefaultLangID_(), @ErrorBufferPointer, 0, 0)
  If ErrorBufferPointer <> 0
    ErrorText = PeekS(ErrorBufferPointer)
    LocalFree_(ErrorBufferPointer)
    ProcedureReturn RemoveString(ErrorText, #CRLF$)
  EndIf
  
EndProcedure

#FileIO = 1

Define sFileFullPath.s = "D:\Folder1\Folder2\Folder3\Folder4\MyFile.txt"

Debug CreateDirectory("D:\Folder1\")
Debug CreateDirectory("D:\Folder1\Folder2\")
Debug CreateDirectory("D:\Folder1\Folder2\Folder3\")
Debug CreateDirectory("D:\Folder1\Folder2\Folder3\Folder4\")
If CreateFile(#FileIO, sFileFullPath, #PB_UTF8)
  CloseFile(#FileIO)
Else
  Debug GetLastError() ; <<<
EndIf
The function GetLastError() returns the last error. E.g. "System cannot find the path specified.", if the directory does not yet exist.
Image
Image
Marc56us
Addict
Addict
Posts: 1477
Joined: Sat Feb 08, 2014 3:26 pm

Re: CreateDirectory -> CreateFile

Post by Marc56us »

There are many cases, and not only in PB, where system operations on file accesses fail because it goes too fast. Often a simple 1, 100 or 500 ms delay is enough to solve the problem and will be invisible to the user.
I often had cases where a Delay(1) solved my problem (without me understanding why) ?

And, as a precaution, it is often necessary to construct the operations (systems) in cascade

Not

Code: Select all

CreateDirectory("D:\Folder1\")
CreateDirectory("D:\Folder1\Folder2\")
CreateDirectory("D:\Folder1\Folder2\Folder3\")
CreateDirectory("D:\Folder1\Folder2\Folder3\Folder4\")
But

Code: Select all

If CreateDirectory("D:\Folder1\")
  If CreateDirectory("D:\Folder1\Folder2\")
    If CreateDirectory("D:\Folder1\Folder2\Folder3\")
      If CreateDirectory("D:\Folder1\Folder2\Folder3\Folder4\")
(With Delay() and Break inside each if /EndIf)

:wink:
kvitaliy
Enthusiast
Enthusiast
Posts: 162
Joined: Mon May 10, 2010 4:02 pm

Re: CreateDirectory -> CreateFile

Post by kvitaliy »

Code: Select all

int SHCreateDirectory(
  _In_opt_ HWND   hwnd,
  _In_     PCWSTR pszPath
);
This function creates a file system folder whose fully qualified path is given by pszPath. If one or more of the intermediate folders do not exist, it creates them.

Code: Select all

SHCreateDirectory_(0, "D:\Folder1\Folder2\Folder3\Folder4")
Returns ERROR_SUCCESS if successful. If the operation fails, other error codes can be returned, including those listed here.

Code: Select all

Procedure.s MakeSureDirectoryPathExists(Directory.s)
    ErrorCode.i = SHCreateDirectory_(#Null, Directory.s)
    Select ErrorCode.i
    Case #ERROR_SUCCESS               : Message.s ="Okay"                                           ; ResultCode = 0
    Case #ERROR_BAD_PATHNAME          : Message.s ="Bad directory path"                             ; ResultCode = 161
    Case #ERROR_FILENAME_EXCED_RANGE  : Message.s ="Directory path too long"                        ; ResultCode = 206
    Case #ERROR_FILE_EXISTS           : Message.s ="Directory already exists"                       ; ResultCode = 80
    Case #ERROR_ALREADY_EXISTS        : Message.s ="Directory already exists"                       ; ResultCode = 183

  EndSelect
 
  ProcedureReturn Message.s
  
EndProcedure
Post Reply