How to detect windows 32bit or 64 bit using NSIS script? - nsis

I have written nsis script for java project.I have Batch file in my project.I have written batch file for commonly windows 32bit and 64 bit.After installing i have started batch file automatically using Exec command.Its woks fine in 32bit windows.but the same time this is not worked well in 64 bit.so i suspect that before installing i should check whether windows is 32 bit or 64 bit version.please share your views how to check?

For future lazy googlers - A small snippet:
Include this:
!include x64.nsh
And use this if:
${If} ${RunningX64}
# 64 bit code
${Else}
# 32 bit code
${EndIf}

Use the RunningX64 macro in the x64.nsh header:
!include LogicLib.nsh
!include x64.nsh
Section
${If} ${RunningX64}
DetailPrint "64-bit Windows"
${Else}
DetailPrint "32-bit Windows"
${EndIf}
SectionEnd

Here's what I use most of the time without the need for x64.nsh
Var Bit
System::Call "kernel32::GetCurrentProcess()i.s"
System::Call "kernel32::IsWow64Process(is,*i.r0)"
StrCmpS $0 0 +3
StrCpy $Bit 64
Goto +2
StrCpy $Bit 32
Now $Bit holds either 64 or 32 which can be used like this:
${If} $Bit == 64
...64-bit code..
${Else}
..32-bit code...
${EndIf}
Or
StrCmpS $Bit 64 SixtyFour ThirtyTwo
SixtyFour:
...
Goto End
ThirtyTwo:
...
End:
I used StrCmpS as I believe it's a hair faster. Lol. Hope this helps! =)

Related

How to stop the uninstallation and pop up a message box when uninstalling in Safe mode using NSIS?

How to stop the uninstallation and pop up a message box (something like as shown below) when uninstalling the installed software using NSIS if the operating system is in Safe mode.
!include LogicLib.nsh
Function un.onInit
!define /IfNDef SM_CLEANBOOT 67
System::Call 'USER32::GetSystemMetrics(i${SM_CLEANBOOT})i.r0'
${If} $0 <> 0
MessageBox mb_IconStop "Safe mode blah blah"
Quit
${EndIf}
FunctionEnd

Check/Prevent Windows Shutdown (NSIS)

To summarize, I need to check and/or prevent a user if he/she decides to shutdown the computer while the installer is running. Now I've researched for a while and came up with the following:
${If} ${AtMostWinXP}
System::Call `kernel32::GetModuleHandle(i0)i.r3`
System::Call `user32::CreateWindowEx(i0,t"STATIC",t"MyApp",i0,i0,i0,i0,i0,i$HWNDPARENT,i0,ir3,i0)i.r1`
${ElseIf} ${AtLeastVista}
System::Call `user32::ShutdownBlockReasonCreate(ir1,w"MyApp is running and still needs to clean up before shutting down!")i.r0`
${EndIf}
However the above snippet isn't working. Am I missing something? I've tried using just:
System::Call `kernel32::GetModuleHandle(i0)i.r3`
System::Call `user32::CreateWindowEx(i0,t"STATIC",t"MyApp",i0,i0,i0,i0,i0,i$HWNDPARENT,i0,ir3,i0)i.r1`
System::Call `user32::ShutdownBlockReasonCreate(ir1,w"MyApp is running and still needs to clean up before shutting down!")i.r0`
As the first two calls are meant for Windows XP and earlier and the third call is meant for Windows Vista or later but is ignored by Windows XP and earlier I believe (I have no evidence to support this theory). This too isn't working.
Also, I can use user32::ShutdownBlockReasonCreate(ir1,w"$(PreventShutdown)")i.r0 instead of using the entire string in the above snippet for different language support, right?
Your code for Windows XP makes no sense, the window needs to handle WM_QUERYENDSESSION to block the shutdown. Luckily NSIS already handles WM_QUERYENDSESSION for you.
Use something like this for Vista and later:
LoadLanguageFile "${NSISDIR}\Contrib\Language Files\English.nlf"
LangString BlockReason ${LANG_ENGLISH} "Installer blah blah"
LoadLanguageFile "${NSISDIR}\Contrib\Language Files\Swedish.nlf"
LangString BlockReason ${LANG_SWEDISH} "Installer bork bork"
!include nsDialogs.nsh ; For WS_CHILD
!define /ifndef WS_POPUP 0x80000000
!include LogicLib.nsh
Function CreateShutdownBlockReason
StrCpy $1 $hwndParent
${If} $1 Z= 0 ; $hwndParent is 0, create a new window for silent installers
System::Call 'USER32::CreateWindowEx(i0, t "STATIC", t "$(^Name)", i ${WS_CHILD}|${WS_POPUP}, i0, i0, i0, i0, p r1, i0, i0, i0)p.r1'
${EndIf}
System::Call 'USER32::ShutdownBlockReasonCreate(p r1, w "$(BlockReason)")'
FunctionEnd
Function .onInit
IfSilent 0 +2
Call CreateShutdownBlockReason ; .onGuiInit is not executed in silent installers
FunctionEnd
Function .onGuiInit
Call CreateShutdownBlockReason
FunctionEnd
I'm not sure if a silent installer will be able to block the shutdown but this is the best you can do without a plug-in.

Can i detect 32 or 64 bit OS without plugin somehow?

now i use the x64.nsh for this, but i can detect it without this plugin?
${If} ${RunningX64}
MessageBox MB_OK "running on 64 bit"
File /r ${64BIT_OPENVPN_INSTALL}
Execwait ${64BIT_OPENVPN_INSTALL}
${Else}
MessageBox MB_OK "running on 32 bit"
File /r ${32BIT_OPENVPN_INSTALL}
Execwait ${32BIT_OPENVPN_INSTALL}
${EndIf}
x64.nsh does not implies specific external plugin usage (apart the system plugin): it is just an included file that defines 3 macros based on kernel calls (i.e kernel32::GetCurrentProcess() and kernel32::IsWow64Process()) through the system plugin, that can be conveniently used with LogicLib.nsh
There are probably many ways to detect the native bitness by just looking at files and registry keys but there is always the risk that some 32-bit systems have somehow ended up with a SysWOW64 folder in %WinDir% etc.
The SetRegView test should be pretty safe but there is a small window where some other app could change the registry at just the wrong time giving you the wrong result.
The correct way to detect this is of course to call the IsWow64Process function and the x64.nsh header already does that for you.
!include LogicLib.nsh
Section
!if "${NSIS_PTR_SIZE}" > 4
DetailPrint "64-bit NSIS, this must be a 64-bit system"
!endif
${If} ${FileExists} "$WinDir\SysWOW64\kernel32.dll"
DetailPrint "Probably not a native 32-bit system"
${EndIf}
${If} ${FileExists} "$WinDir\SysNative\kernel32.dll"
DetailPrint "Probably a 32-bit app on a native 64-bit system (Vista+ only)"
${EndIf}
SetRegView 64
ReadRegStr $6 HKLM "Software\Microsoft\Windows\CurrentVersion" "ProgramFilesDir"
SetRegView lastused
SetRegView 32
ReadRegStr $3 HKLM "Software\Microsoft\Windows\CurrentVersion" "ProgramFilesDir"
SetRegView lastused
${If} $3 != $6
DetailPrint "Probably a 32-bit app on a native 64-bit system"
${EndIf}
; ReadEnvStr on ProgramW6432 or PROCESSOR_ARCHITEW6432 etc
SectionEnd

Having InstallDir within IF ELSE block

I try to have the following code from
; The default installation directory
InstallDir $PROGRAMFILES\${PRODUCT_NAME}
to
!include x64.nsh
${If} ${RunningX64}
; The default installation directory
InstallDir $PROGRAMFILES\${PRODUCT_NAME}
${Else}
; The default installation directory
InstallDir $PROGRAMFILES64\${PRODUCT_NAME}
${EndIf}
I get the following error :-
!insertmacro: _If
Error: Can't add entry, no section or function is open!
Error in macro _RunningX64 on macroline 2
Error in macro _If on macroline 9
Error in script "C:\Users\yccheok\Desktop\mysoftware.nsi" on line 17 -- aborting creation process
Is there way I can set the value for InstallDir, within if else block?
If you need a dynamic $InstDir you should not use InstallDir at all but set $InstDir in .onInit:
Installdir ""
!include LogicLib.nsh
!include x64.nsh
Function .onInit
${If} $InstDir == "" ; /D= was not used on the command line
${If} ${RunningX64}
StrCpy $InstDir "c:\foo"
${Else}
StrCpy $InstDir "c:\bar"
${EndIf}
${EndIf}
FunctionEnd
Your current if else block does not make any sense because you are selecting the 32 bit program files on x64 and the 64 bit program files on x86! It is OK to use $PROGRAMFILES64 on x86 so if you always want the "real" program files you can use $PROGRAMFILES64 for all platforms...

x64.nsh not working

I have encountered a piece of code in the web...
I have 64.nsh in my machine and as an example I have included in my code the following:
${If} ${RunningX64}
MessageBox MB_OK "running on x64"
${EndIf}
And it returns:
!insertmacro:
_If !insertmacro: macro "_If" requires 4 parameter(s), passed 2!
Could you help?
Thanks in advance!
Having the file on your system is not enough, you need to include the file in your code:
!include "x64.nsh"
${If} ${RunningX64}
MessageBox MB_OK "running on x64"
${EndIf}

Resources