get hard disk drive name in which windows OS installed using NSIS - nsis

I need to get hard disk drive letter like C: or D: or any in which the OS is installed on any windows.
Kindly help me get out of this.

Section
StrCpy $0 $sysdir 3
DetailPrint $0
SectionEnd
$SYSDIR is the Windows system directory (usually C:\Windows\System or C:\WinNT\System32, but that's detected at runtime).
StrCpy has the syntax StrCpy user_var(destination) str(source) [maxlen] [start_offset] where maxlen and start_offset are optional.
So the code above, copies the first three letters from $SYSDIR into the $0 variable.

Related

How to check the space in the drive by taking the path from the Destination Folder When installing the software using NSIS

How to check the space in the drive by taking the path from the Destination Folder When installing the software.
I am able to check the space of the specific drive (for eg, "C") using the below code snippet.
But I want to take the drive or path from the Destination folder dynamically and check the space of the drive whether there is enough space or not.
!define sysGetDiskFreeSpaceEx 'kernel32::GetDiskFreeSpaceExA(t, *l, *l, *l) i'
function CheckSpaceFunc
IntCmp $2 0 ignorequota
; obey quota
System::Call '${sysGetDiskFreeSpaceEx}(r1,.r2,,.)'
goto converttokb
; ignore quota
ignorequota:
System::Call '${sysGetDiskFreeSpaceEx}(r1,.,,.r2)'
converttokb:
; convert the large integer byte values into managable kb
System::Int64Op $2 / 1024
Pop $2
; check space
System::Int64Op $2 > $0
Pop $2
functionend
Section "TestApp"
SectionIn RO
StrCpy $0 40000 ; kb u need
StrCpy $1 'c:' ; check drive c: for space
Call CheckSpaceFunc
IntCmp $2 1 okay
MessageBox MB_OK "Error: Not enough disk space"
okay:
SectionEnd
Could anyone please help me
The built-in directory page (Page Directory or !insertmacro MUI_PAGE_DIRECTORY) will perform the free space check for you and takes care of all the details.
It might be tempting to just do StrCpy $1 $InstDir 3 to get the drive letter and perform the check yourself but this can give you the wrong result because NTFS supports mounting other volumes as a folder.
GetDiskFreeSpaceEx does support directory paths but I believe the path has to exist so if you want to use $InstDir before $InstDir has been created then you must chop off subfolders until GetDiskFreeSpaceEx succeeds (or you only have a invalid drive letter left of the path).
Your !define should also be changed from GetDiskFreeSpaceExA to GetDiskFreeSpaceEx because it uses the t string type. This will make it Unicode compatible.

Version comparison in NSIS installer

I have to compare the versions of current file and already the installed in NSIS installer. I understand the version numbers are in string but I read at couple of places that the NSIS automaticaly converts the strings to intergers if needed in logic operations.
Just for the test purpose, I wrote the following script:
Var Test1
Var Test2
section
StrCpy $Test1 "4.3.1.50245"
StrCpy $Test2 "4.2.1.50245"
${If} $Test1 > $Test2
MessageBox MB_ICONSTOP "$Test1 is bigger than $Test2"
${Else}
MessageBox MB_ICONSTOP "$Test2 is bigger than $Test1"
${EndIf}
Quit
sectionEnd
PROBLEM: It gives me the result 4.2.1.50245 is greated than 4.3.1.50245. However, it gives me correct results if I try to compare 4.2.1.50245with 3.2.1.50245 (or if I compare 50245and 40256 etc.)
Check out the following function, Version Compare
http://nsis.sourceforge.net/VersionCompare
Section
${VersionCompare} "1.1.1.9" "1.1.1.01" $R0
; $R0="1"
SectionEnd
; Result:
; $var=0 Versions are equal
; $var=1 Version1 is newer
; $var=2 Version2 is newer
If not, another method would be to implement an Explode of the string and then compare the Major, Minor, Revision, ... portions. But that may be overkill:
http://nsis.sourceforge.net/Explode

Checking for Registry in NSIS

I'm using NSIS to make an executable for a project I'm doing in Visual C++ 2012 Express. Because I'm a beginner, I started with the Setup Wizard in HM NIS Edit.
I'm trying to bundle the Visual C++ 2012 Redistributable with my program, but every time the installer is re-ran, the Redistributable pops up with a "Repair" & "Remove" option, and that looks annoying.
So I decided to write a little bit of NSIS script, and this is the start of the script so far:
Var STR
Section CheckForReg
ClearErrors
ReadRegDWORD $0 HKLM "SOFTWARE\Classes\Installer\Dependencies\{8e70e4e1-06d7-470b-9f74-a51bef21088e}" "Version"
ifErrors 0 Blank
StrCpy $STR "$INSTDIR\vcredist_x86.exe"
GoTo End
Blank:
StrCpy $STR ""
End:
SectionEnd
This piece is called at the very start of the script, and the global variable STR is applied to:
!define MUI_FINISHPAGE_RUN $STR
Shortly after.
Obviously this is a really silly way to do it, but I don't need too much out of it.
The issue is that the CheckForReg always thinks the registry doesn't exist, and doesn't move to the label Blank. As a note, I'm manually checking the registry every time, and the registry entry looks like:
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Dependencies\{8e70e4e1-06d7-470b-9f74-a51bef21088e}]
"Version"="11.0.51106.1"
"DisplayName"="Microsoft Visual C++ 2012 Redistributable (x86) - 11.0.51106"
So the question is: Where am I going wrong with this? It looks very simple, but obviously I have something backwards.
-- Removed Code Dump
You can only read DWORDs with ReadRegDWORD!
!include LogicLib.nsh ; So we don't have to use all these labels
StrCpy $STR ""
ReadRegStr $0 HKLM "SOFTWARE\Classes\Installer\Dependencies\{8e70e4e1-06d7-470b-9f74-a51bef21088e}" "Version"
${If} $0 == ""
StrCpy $STR "$INSTDIR\vcredist_x86.exe"
${EndIf}

How to get system drive volume serial number

I am building a setup which requires to retrieve the disk volume of the drive on which the Operating system is installed. I have tried the following code:
Function ShowDiskVolumeSerialNumber
!define GetVolumeInformation "Kernel32::GetVolumeInformation(t,t,i,*i,*i,*i,t,i) i"
System::Call '${GetVolumeInformation ("$0",,${NSIS_MAX_STRLEN},.r0,,,,${NSIS_MAX_STRLEN})'
IntFmt $0 "%08X" $0
MessageBox MB_OK $0
FunctionEnd
I call the above function by specifying the desired drive:
StrCpy $0 "C:\"
Call ShowDiskVolumeSerialNumber
The above gives the volume no of c:\ drive. However if my OS is installed on d:\ or e:\ it will not work. I want a function which will automatically detect the drive on which the OS is installed and retrieve its volume no.
Secondly, the volume number retrieved is without a hyphen (e.g. 349620C1). I need the volume serial number retrieved as 3496-20C1.
Could someone please give a complete NSIS function when will do both the things i.e:
Automatically detect the drive on which the OS is installed and retrieve its serial no with a hyphen in between.
To get the OS drive, StrCpy $0 $windir 3 is probably enough (You did not specify if you wanted the boot volume or the system volume, on most systems they are the same so $windir is a good starting point)
To edit the serial number:
StrCpy $0 $serial 4
StrCpy $serial $serial "" 4
StrCpy $serial "$0-$serial"

NSIS: environment variable created doesn't work

I am creating a Env Variable and then appending it to the PATH variable in my NSIS installer script on Win7 - 64 bit.
Push "MyPath"
Push "D:\MyFolder\bin;D:\MyFolder\lib"
Call WriteEnvStr
Push "%MyPath%"
Call AddToPath
Now after installation I can see both the variable in cmd prompt
MyPath=D:\MyFolder\bin;D:\MyFolder\lib
Path=%MyPath%;<my existsing path>
But any exe/dll from are not found at run time.
If I run the cmd prompt as Administrator and then run exe, it runs fine.
It also works if I run exe directly as an Administrator.
Also interesting is that if I open Environment editor, double click on MyPath variable and click OK (without changing anything), my exe's run fine without running as Administrator.
And now if I check Path in cmd prompt, MyPath variable is substituted
MyPath=D:\MyFolder\bin;D:\MyFolder\lib
Path=D:\MyFolder\bin;D:\MyFolder\lib;<my existsing path>
I tried to add "Call EnvVarUpdate" after creating the env variable but it doesn't work.
I am using NSIS Unicode version 2.46.3
Your chances of adding/modifying the path without losing data in path by truncating it would be much greater by using the registry.
ReadRegStr $0 HKCU "Environment" Path
StrCpy $1 "D:\MyFolder\bin;D:\MyFolder\lib"
StrCpy $2 "$0;$1"
WriteRegStr HKCU "Environment" Path "$2"
If your system has an AUTOEXEC.BAT file then any PATH setting in AUTOEXEC.BAT will also be appended to the %PATH% environment variable. This is to provide compatibility with old installation routines which need to set the PATH. All other commands in AUTOEXEC.BAT are ignored however. And this is more or less obsolete anyway.
But we could just continue with your method however just try a different means of acomplishing your goal. I have not tested this but you can try something similar to this:
StrCpy $R0 "MYPATH"
StrCpy $R1 "D:\MyFolder\bin;D:\MyFolder\lib"
System::Call `Kernel32::SetEnvironmentVariable(t"$R0",t"$R1")`
Now include your new variable in the path like the following:
ReadEnvStr $R0 COMSPEC
ReadEnvStr $R1 MYPATH
ExecDos::Exec /TOSTACK `"$R0" /c "SetX PATH=%PATH%;$R1 -m"`
You can now easily change that one variable %MYPATH% at any time in the future and the PATH will reflect the new value.
${EnvVarUpdate} $0 "PATH" "A" "HKLM" "C:\Program Files\Java\jre6\bin"
StrCpy $R0 "$0"
System::Call 'Kernel32::SetEnvironmentVariableA(t, t) i("PATH", R0).r2'
ReadEnvStr $R0 "PATH"
ExecWait "$INSTDIR\tmp\batchfile.bat

Resources