Skip to content
⌘ NSIS Forum Archive

Under what condition would CreateDirectory failed?

16 posts

totszwai#

Under what condition would CreateDirectory failed?

Hello,

I am experiencing a really weird condition with the NSIS install script... So I created an installed that is all working fine on my local computer, either I ran it as normal user or as administrator. However, when the customer tried to run it in their machine, the installer ran fine (CreateDirectory did not throw any error) however the directory was never created.

The directory in question is just
$APPDATA\Blah
, where $APPDATA typically points to my own Roaming folder, ex: C:\Users\et5341\AppData\Roaming



Could any experts here give me some hint on how to troubleshoot this issue?
  • Why was the "Blah" folder never created under Roaming?
  • Installer was ran as normal user or administrator, both never created the folder.
  • Is a Windows 10 machine, although I tried it on my Windows 11 and even XP, it worked fine.
  • Is it because or some kind of permission issue of the Roaming folder?

Regards,
totszwai#
Ah dang it, I can't edit the post? This is the section I had in the installer script



Section -StartMenu
SetOutPath "$INSTDIR"
CreateDirectory "$APPDATA\Blah"
CreateDirectory "$SMPROGRAMS\Blah"
CreateShortCut "$SMPROGRAMS\Blah\My App.lnk" \
"$INSTDIR\my-app.exe" "" \
"$INSTDIR\${MUI_ICON}" 0
SectionEnd​

Anders#
If a normal user (non-admin) runs the installer elevated, $APPDATA​ will point to the administrators profile, not the normal user.

If you call "SetShellVarContext all", $APPDATA​​ will be something like c:\ProgramData.

Other than that, I don't see why it would fail other than regular access denied errors.

Try adding "DetailPrint $APPDATA​" before CreateDirectory​ to make sure you have the path you expect.
totszwai#
I ran it with DetailPrint, but the log disappear so fast that I can't really see what's up with it. I can't really run the save log file build either, since that's unavailable to MSYS2/MinGW.
Is there a "Wait for user to confirm" feature from NSIS that I could use before stepping it to the next step?

Originally Posted by Anders View Post
If a normal user (non-admin) runs the installer elevated, $APPDATA​ will point to the administrators profile, not the normal user.
Ok this is what I don't understand, consider the following 2 scenario:
  • ME (the dev, Windows 11, normal user account with admin privileges within my laptop), ran the installer in BOTH non-admin and admin, both scenarios were able to create the directory $APPDATA/Blah
  • User (the consumer, a corporate user, Windows 10, normal user without admin privileges, and possibly with more restrictions on their account)
Does the end user need to install some sort of NSIS related packages before they run the installer?
Maybe some sort of security updates from Microsoft before they could properly get CreateDirectory to work?

Anders#
MessageBox mb_ok "$AppData" would stop everything. The user can press Ctrl+C to copy the text. Or you can use WriteIniStr to write to a .ini.

The 2 scenarios are as expected, this is just how UAC works.

If you are in the administrators group then it does not matter if you UAC elevate or not, $Appdata will always be "correct".

On the other hand, if you have a non-admin user named Foo then you are expecting $Appdata to be c:\users\Foo\Appdata\Roaming but if the installer is UAC elevated then $Appdata will actually be c:\users\Administrator\Appdata\Roaming.

Technically, if you put "RequestExecutionLevel User" in your .nsi then $Appdata will be correct but you cannot write to $ProgramFiles nor HKLM. If you put "RequestExecutionLevel Admin" then you can write to $ProgramFiles and HKLM but you should not touch the users $Appdata nor HKCU.
totszwai#
Anders I added a "Sleep" and was able to capture this screenshot before it disappear. It looks like there is some kind of corrupted text at the end of the variable $APPDATA?

There is nothing else appended to it, this is the output of the following instruction:

DetailPrint "$APPDATA​"
Click image for larger version

Name:	image.png
Views:	191
Size:	29.6 KB
ID:	4618313
Anders#
Please compile this and report the result

RequestExecutionLevel User
ShowInstDetails Show
Section
DetailPrint "NSIS ${NSIS_VERSION} ${NSIS_PACKEDVERSION} ${NSIS_CHAR_SIZE} ${NSIS_PTR_SIZE}"
GetDllVersion "$SysDir\GDI32.dll" $1 $2
IntOp $5 $2 / 0x00010000
GetDllVersion "$SysDir\MSFTEdit.dll" $1 $2
IntOp $6 $2 / 0x00010000
GetDllVersion "$SysDir\NTOSKrnl.exe" $1 $2
IntOp $7 $2 / 0x00010000
System::Call 'SHELL32::#680()i.r0'
DetailPrint "GDI32=$5 MSFTE=$6 NTOS=$7 | $0"
DetailPrint "$$Appdata=$AppData"
DetailPrint "$$LocalAppdata=$LocalAppData"
DetailPrint "$$Profile=$Profile"
ReadRegStr $0 HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" "AppData"
DetailPrint "HKCU:USF:AD=$0"
ReadRegStr $0 HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" "AppData"
DetailPrint "HKCU:SF:AD=$0"
ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}" "RelativePath"
DetailPrint "HKLM:FD:AD=$0"
System::Call 'SHELL32::SHGetFolderPathA(p0,i0x1a,p0,i0,m.r1)i.r0'
DetailPrint A:$0=$1
System::Call 'SHELL32::SHGetFolderPathW(p0,i0x1a,p0,i0,w.r1)i.r0'
DetailPrint W:$0=$1
SectionEnd​​ 

(You can right-click the log window to copy to the clipboard)

Also, !define MUI_FINISHPAGE_NOAUTOCLOSE​ at the top of your .nsi to prevent it skipping to the next page.
totszwai#
Originally Posted by Anders View Post
Please compile this and report the result.
I could not use RequestExecutionLevel User, as it won't even install it into ProgramFiles folder.

NSIS v3.08 0x03008000 2 8
GDI32=22621 MSFTE=22621 NTOS=22621 | 1
$Appdata=C:\Users\et5341\AppData\Roaming
$LocalAppdata=C:\Users\et5341\AppData\Local
$Profile=C:\Users\et5341
HKCU:USF:AD=%USERPROFILE%\AppData\Roaming
HKCU:SF:AD=C:\Users\et5341\AppData\Roaming
HKLM:FD:AD=AppData\Roaming
A:0=C:\Users\et5341\AppData\Roaming
W:0=C:\Users\et5341\AppData\Roaming​ 
I found a really surprising discovery using your code! Calling $APPDATA (all in caps) would yield the weird character at the end of the string! However, using $AppData prints it nicely.

MessageBox MB_OK "$APPDATA"
# prints C:\Users\et5341\AppData\Roaming​ MessageBox MB_OK "$AppData"
# prints C:\Users\et5341\AppData\Roaming 
Is $APPDATA also an official variable provided by NSIS? Or it something else?
totszwai#
Originally Posted by Anders View Post
You are using a 64-bit build, where did you get it from?
If you are referring to the nsis building utility, I installed them via MSYS2's pacman



Anders#
Try these 3 files I attached and see if all of them are broken...
Anders#
Originally Posted by Anders View Post
Please compile this and report the result
Please take that code from above (and no other code) and change AppData to uppercase so that it fails and upload the .exe for me to test.

totszwai#
Originally Posted by Anders View Post
Please take that code from above (and no other code) and change AppData to uppercase so that it fails and upload the .exe for me to test.
Ok, so the only "difference" is that when is not working, it happens on the Windows 10 machine, but it works fine on mine (Windows 11).

This is my colleague's reported value:
========== Environment Infomation ==========
NSIS v3.08 0x03008000 2 8
GDI32=19041 MSFTE=19041 NTOS=19041 | 1
$AppData=C:\Users\jaysona\AppData\Roaming
$APPDATA=C:\Users\jaysona\AppData\Roaming
$LocalAppData=C:\Users\jaysona\AppData\Local
$Profile=C:\Users\jaysona
HKCU:USF:AD=%USERPROFILE%\AppData\Roaming
HKCU:SF:AD=C:\Users\jaysona\AppData\Roaming
HKLM:FD:AD=AppData\Roaming
A:0=C:\Users\jaysona\AppData\Roaming
W:0=C:\Users\jaysona\AppData\Roaming
Username: jaysona, Number of characters: 8, Return value (OK if non-zero): 1​
This is on my machine (that worked fine for me), it literally is just the same thing:
========== Environment Infomation ==========
NSIS v3.08 0x03008000 2 8
GDI32=22621 MSFTE=22621 NTOS=22621 | 1
$AppData=C:\Users\et5341\AppData\Roaming
$APPDATA=C:\Users\et5341\AppData\Roaming
$LocalAppData=C:\Users\et5341\AppData\Local
$Profile=C:\Users\et5341
HKCU:USF:AD=%USERPROFILE%\AppData\Roaming
HKCU:SF:AD=C:\Users\et5341\AppData\Roaming
HKLM:FD:AD=AppData\Roaming
A:0=C:\Users\et5341\AppData\Roaming
W:0=C:\Users\et5341\AppData\Roaming
Username: et5341, Number of characters: 7, Return value (OK if non-zero): 1​

One thing we noted is that, for some reason, the username is N character, but the "Number of characters" would always be N+1 for some reason... Is that a bug?
totszwai#
I also want to add that, both of the accounts have the same privileges, like both of them were
  • Local Account
  • Administrator Account
Anders#
This is my colleague's reported value
This looks correct to me, where is the bug?

Regarding the length, I don't know the code used for the length, you would have to post it.


​​​​​​Finally, you keep using this 3rd-party 64-bit build, it would be nice if you could reproduce it with the official 32-bit build...