I have this really niche problem,
I am an assetto corsa modder, I make add-ons based on cars already in the game. I can't give it all the files because it could give people dlc's they haven't bought. (not looking to be sued)
So I need to find the specific car folder on someone's computer, then copy all files in it and install some more with it. My problem; I am unable to automate the finding proces. Some have it on C:\ , some on D:\ , etc.
My current Manual methode, this works but I got loads of negative feedback about it:
!include "nsDialogs.nsh"
!include "LogicLib.nsh"
Name "Vismonger mod installation"
Outfile "Toyota Supra MKIV Tuned LHD.exe"
InstallDir "C:\Program Files (x86)\Steam\steamapps\common\assettocorsa\content\cars\ks_toyota_supra_mkiv_tuned_lhd" ;most probable $INSTDIR
RequestExecutionLevel admin
XPStyle on
Icon "D:\Downloads\assetto autos\installer\data\upgrade.ico" ;path to icon
Var Dialog
Var SOURCE_DIR
Page components
Page custom nsDialogsPage
Page directory
Page instfiles
Function nsDialogsPage
nsDialogs::Create 1018
Pop $Dialog
;make them select the folder themselves
nsDialogs::SelectFolderDialog "Please select the 'ks_toyota_supra_mkiv_tuned' folder in assetto corsa's game files" "C:\Program Files (x86)\Steam\steamapps\common\assettocorsa\content\cars"
Pop $SOURCE_DIR ;$SOURCE_DIR is now the wanted directory
${If} $Dialog == error
Abort
${EndIf}
FunctionEnd
Section "Toyota Supra MKIV Tuned LHD" SEC01
; Copy files from the selected source directory to the destination directory
SetOutPath $INSTDIR
CopyFiles "$SOURCE_DIR\*.*" $INSTDIR
; Copy specific files from my fixed location and install to the destination directory
SetOutPath $INSTDIR
File /r "D:\Downloads\assetto autos\installer\data\ks_toyota_supra_mkiv_tuned_lhd\*.*"
SectionEnd
I tried this with the help of a million forums, just to find and present me the directory on the correct drive before even attempting to implement it into my installation code:
!include LogicLib.nsh
!include FileFunc.nsh
Name "SearchDirectoryExample"
OutFile "SearchDirectoryExample.exe"
RequestExecutionLevel user
Section "Search Directory" SEC01
InitPluginsDir
StrCpy $0 0 ; Drive index
System::Call 'KERNEL32::GetLogicalDrives() i.r1'
loop:
IntOp $2 $1 & 1
StrCmp $2 0 next
System::Call 'KERNEL32::GetVolumeInformation(t " $0:\") i .r3 t .r4 i .r5 i .r6 .r7'
StrCmp $3 "" next
; Check if the directory exists on this drive
IfFileExists "$0:\Program Files (x86)\Steam\steamapps\common\assettocorsa\content\cars\ks_toyota_supra_mkiv_tuned\*" 0 found
found:
DetailPrint "Found directory on drive $0:"
DetailPrint "$0:\Program Files (x86)\Steam\steamapps\common\assettocorsa\content\cars\ks_toyota_supra_mkiv_tuned"
MessageBox MB_OK "Found directory on drive $0:`n$0:\Program Files (x86)\Steam\steamapps\common\assettocorsa\content\cars\ks_toyota_supra_mkiv_tuned"
Goto done
next:
IntOp $0 $0 + 1
IntOp $1 $1 >> 1
StrCmp $0 26 loop
done:
SectionEnd
But that doesn't seem to do anything.
I am really a newbie to this and I only know python and nsis. I have searched for hours but couldn't find anything that relates to my problem or what could be of interest to me. I would like my old code but with the manual directory selection changed out with a working automatic one. (which was my original idea obv.).
Enumerating drive letters:
!include LogicLib.nsh
Section
StrCpy $0 0 ; Drive index
System::Call 'KERNEL32::GetLogicalDrives()i.r1'
loop:
${If} $1 & 1
IntOp $2 $0 + 65
System::Call 'USER32::wsprintf(t.r2, t "%c", ir2)?c'
System::Call 'KERNEL32::GetDriveType(t "$2:\")i.r4'
DetailPrint "Drive letter $2 is valid and is of type $4"
${If} $4 <> 1 ; Skip DRIVE_NO_ROOT_DIR
${AndIf} $4 <> 5 ; Skip DRIVE_CDROM
StrCpy $3 ":\Program Files (x86)" ; Default
; Use the correct program files path if possible (optional)
StrCpy $4 $ProgramFiles32 2 1 ; Extract substring so we can check if it is a drive or a network share
${IfThen} $4 == ":\" ${|} StrCpy $3 $ProgramFiles32 "" 1 ${|}
StrCpy $2 "$2$3"
DetailPrint "The file might be somewhere inside $2\..."
${EndIf}
${EndIf}
${If} $0 < 26
IntOp $0 $0 + 1
IntOp $1 $1 >>> 1
Goto loop
${EndIf}
SectionEnd
Use FindFirst
, FindNext
and FindClose
in a recursive function if you want to search inside all folders in a drive (might be too slow).