Creating an empty directory (NSIS)
Asked Answered
B

4

6

How can I do it by NSIS 2.46?

I know this is probably a dumb question, but how the heck do I create an empty directory and check for errors?

I do so:

ClearErrors
CreateDirectory $R1
${If} ${Errors} 
  DetailPrint "failed"
  MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Can not create folder $R1"
  Abort
${Else}
  DetailPrint "done"
${EndIf}

if the variable $R1 is

  • "c:\test" - done
  • "c:\con" - failed ("con" - reserved on Windows)
  • "qwer:\test2" - done
  • "qwer\test3" - done (without ":")

why "test2" and "test3" without errors?

UPDATE: How to make that it was an error?

Bimah answered 27/1, 2015 at 11:30 Comment(0)
B
7

I decided:

ClearErrors
CreateDirectory $R1
${If} ${Errors} 
${OrIfNot} ${FileExists} "$R1\*.*"
  DetailPrint "failed"
  MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Can not create folder $R1"
  Abort
${Else}
  DetailPrint "done"
${EndIf}

have more ideas?

Bimah answered 28/1, 2015 at 13:32 Comment(0)
A
6

In order to check for errors you should check the error flag, which you're doing right. I think the problem is you should use quotes:

CreateDirectory "$R1"
Ambriz answered 27/1, 2015 at 11:59 Comment(0)
A
3

NSIS does some unfortunate (IMHO) path mangling and only accepts : as the 2nd character, otherwise it is silently stripped. This means that "qwer\test2" and "qwer:\test2" are treated the same at run-time. You can verify this by copying it to one of the special path registers:

!macro TestNsisPathMangling p
Push $InstDir
StrCpy $InstDir "${p}"
DetailPrint "Old=${p}"
DetailPrint "New=$InstDir"
Pop $InstDir
!macroend

!insertmacro TestNsisPathMangling "qwer\test2"
!insertmacro TestNsisPathMangling "qwer:\test2"

This leaves us with "qwer\test2" and this is a relative path and those are officially not supported when calling CreateDirectory. If you try this in NSIS 3 you should get:

CreateDirectory: Relative paths not supported

Edit:

If the path is entered by the user you can call the Windows function GetFullPathName to get a absolute/full path:

Push "qwer\test3"
System::Call 'KERNEL32::GetFullPathName(ts,i${NSIS_MAX_STRLEN},t.r1,t)i.r0'
${If} $0 <> 0
    DetailPrint "GetFullPathName=$1"
${Else}
    DetailPrint "GetFullPathName failed"
${EndIf}
Aflame answered 28/1, 2015 at 19:1 Comment(2)
@AndreiKrasutski What does that mean? Just use a full path and you should be OK.Aflame
Variable $R1 sets the user in Page Custom, so it can set a bad directory, but I have to check.Bimah
P
0

The documentation for CreateDirectory -- rather irresponsibly -- plainly says error flag is set leaving ambiguity to an occasional NSIS scripter as to what this means.

To no surprise, error handling in NSIS is documented very sparsely as well... but fortunately they do explain how to catch errors if you read the comments thoroughly.

if it is set, it will goto [first param], otherwise it will goto [second param]

Take special note of the word goto in the docs which is a throwback to GOTO line jumping.

ClearErrors
CreateDirectory $R1
IfErrors 0 +2
Call ErrorHandler

What's not immediately obvious is that +2 JUMPS OVER the error handler. And now one can deduce that 0 will goto the NEXT LINE -- the error handler.

The above example should properly handle an error, given that :ErrorHandler is defined somewhere in your script, which can be replaced with any logic you like.

I recommended ; Commenting heavily as this scripting language can be difficult to read if you don't work with it daily.

Pique answered 10/3, 2018 at 3:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.