During my setup i install redistributables. After installing my program i want to execute the program during the setup. For that the redistributables are needed. But the environment is not refreshed during setup, so i can't start the program. Can i refresh the environtment during the setup, or reread the environment? Or read the system environment which has changed after the redistributable installation?
I need the environment changes made during the installation of the redistributables during the setup.
Thanks for your help.
I had your same issue, that I solved with a workaround, but I came across this solution and I would like to share with you.
This should reload environment variables during setup:
!include LogicLib.nsh
!include WinCore.nsh
!ifndef NSIS_CHAR_SIZE
!define NSIS_CHAR_SIZE 1
!define SYSTYP_PTR i
!else
!define SYSTYP_PTR p
!endif
!ifndef ERROR_MORE_DATA
!define ERROR_MORE_DATA 234
!endif
/*!ifndef KEY_READ
!define KEY_READ 0x20019
!endif*/
Function RegReadExpandStringAlloc
System::Store S
Pop $R2 ; reg value
Pop $R3 ; reg path
Pop $R4 ; reg hkey
System::Alloc 1 ; mem
StrCpy $3 0 ; size
loop:
System::Call 'SHLWAPI::SHGetValue(${SYSTYP_PTR}R4,tR3,tR2,i0,${SYSTYP_PTR}sr2,*ir3r3)i.r0' ; NOTE: Requires SHLWAPI 4.70 (IE 3.01+ / Win95OSR2+)
${If} $0 = 0
Push $2
Push $0
${Else}
System::Free $2
${If} $0 = ${ERROR_MORE_DATA}
IntOp $3 $3 + ${NSIS_CHAR_SIZE} ; Make sure there is room for SHGetValue to \0 terminate
System::Alloc $3
Goto loop
${Else}
Push $0
${EndIf}
${EndIf}
System::Store L
FunctionEnd
Function RefreshProcessEnvironmentPath
System::Store S
Push ${HKEY_CURRENT_USER}
Push "Environment"
Push "Path"
Call RegReadExpandStringAlloc
Pop $0
${IfThen} $0 <> 0 ${|} System::Call *(i0)${SYSTYP_PTR}.s ${|}
Pop $1
Push ${HKEY_LOCAL_MACHINE}
Push "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Push "Path"
Call RegReadExpandStringAlloc
Pop $0
${IfThen} $0 <> 0 ${|} System::Call *(i0)${SYSTYP_PTR}.s ${|}
Pop $2
System::Call 'KERNEL32::lstrlen(t)(${SYSTYP_PTR}r1)i.R1'
System::Call 'KERNEL32::lstrlen(t)(${SYSTYP_PTR}r2)i.R2'
System::Call '*(&t$R2 "",&t$R1 "",i)${SYSTYP_PTR}.r0' ; The i is 4 bytes, enough for a ';' separator and a '\0' terminator (Unicode)
StrCpy $3 ""
${If} $R1 <> 0
${AndIf} $R2 <> 0
StrCpy $3 ";"
${EndIf}
System::Call 'USER32::wsprintf(${SYSTYP_PTR}r0,t"%s%s%s",${SYSTYP_PTR}r2,tr3,${SYSTYP_PTR}r1)?c'
System::Free $1
System::Free $2
System::Call 'KERNEL32::SetEnvironmentVariable(t"PATH",${SYSTYP_PTR}r0)'
System::Free $0
System::Store L
FunctionEnd
Section
Call RefreshProcessEnvironmentPath
SectionEnd
Source: http://forums.winamp.com/showpost.php?p=3028153&postcount=12
Related
My installer working fine without nsdialogs, If i add nsdialogs its not working good.I can't call nsdialogs in correct place.where i need to call nsdialogs?
Var hwnd
Var Dialog
Page custom checkinstall
Page custom nsDialogsPage
.
.
.
Function .onInit
!define MUI_LANGDLL_ALWAYSSHOW
!insertmacro MUI_LANGDLL_DISPLAY
SetShellVarContext all
!insertmacro VerifyUserIsAdmin
FunctionEnd
Function un.onInit
!insertmacro MUI_UNGETLANGUAGE
SetShellVarContext all
SetRebootFlag true
MessageBox MB_OKCANCEL "Are you sure you want to uninstall
${APPNAME}?" IDOK next
Abort
next:
!insertmacro VerifyUserIsAdmin
FunctionEnd
Function un.onUninstSuccess
HideWindow
MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed
from your computer."
FunctionEnd
Function Repair
Call .onInit
FunctionEnd
Function Remove
ExecWait "$INSTDIR\Uninstall.exe"
FunctionEnd
Function checkinstall
ReadRegStr $R0 HKLM \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"UninstallString"
IfFileExists $R0 +1 NotInstalled
Call nsDialogsPage
NotInstalled:
FunctionEnd
Function nsDialogsPage
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
${NSD_CreateRadioButton} 0 5u 100% 10u "Repair"
Pop $hwnd
${NSD_AddStyle} $hwnd ${WS_GROUP}
${NSD_OnClick} $hwnd Repair
${NSD_CreateRadioButton} 0 25u 100% 56u "Remove"
Pop $hwnd
${NSD_OnClick} $hwnd Remove
nsDialogs::Show
FunctionEnd
I can not call nsdialogs correctly. checkinstall function not working at all.I need a correct solution for that.
You are writing the uninstall command to the registry with quotes (correct) but you are not removing the quotes when reading the value so the file exists test is always going to be false.
You should remove the quotes from commands you read from the registry:
Function GetAppFromCommand
Exch $1
Push $2
Push $3
StrCpy $3 ""
StrCpy $2 $1 1
StrCmp $2 '"' qloop sloop
sloop:
StrCpy $2 $1 1 $3
IntOp $3 $3 + 1
StrCmp $2 "" +2
StrCmp $2 ' ' 0 sloop
IntOp $3 $3 - 1
Goto done
qloop:
StrCmp $3 "" 0 +2
StrCpy $1 $1 "" 1 ; Remove initial quote
IntOp $3 $3 + 1
StrCpy $2 $1 1 $3
StrCmp $2 "" +2
StrCmp $2 '"' 0 qloop
done:
StrCpy $1 $1 $3
Pop $3
Pop $2
Exch $1
FunctionEnd
!macro GetAppFromCommand cmd outvar
Push `${cmd}`
Call GetAppFromCommand
Pop ${outvar}
!macroend
Function checkinstall
ReadRegStr $R0 HKLM \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" \
"UninstallString"
!insertmacro GetAppFromCommand $R0 $R0
IfFileExists $R0 +1 NotInstalled
Call nsDialogsPage
NotInstalled:
FunctionEnd
I have tried a lot of possibility with this code but it doesn't work. I need to check a VPN connection. If I run the code firs time it works, but if I don't restart the program and push the button secondly then the program just disappear. Any idea how to fix it? thanks.
Function VpnLoginWindow
${Do}
!insertmacro VpnLoginWindow
StrCpy $4 0
${If} $3 == 1
${Do}
!insertmacro VpnLoginWindow
StrCpy $4 1
StrCmp $3 "0" 0 +2
${ExitDo}
${Loop}
${EndIf}
${If} $4 == 1
${ExitDo}
${EndIf}
${Loop}
FunctionEnd
!macro VpnLoginWindow
StrCpy $5 $1
System::Get "(i.r1) iss"
Pop $R0
System::Call "user32::EnumWindows(k R0, i) i.s"
${Do}
Pop $0
StrCmp $0 "1" 0 +2
${ExitDo}
System::Call "user32::GetWindowText(ir1,t.r2,i ${NSIS_MAX_STRLEN})"
StrCpy $2 $2 7
StrCpy $3 0
${If} $2 == "SSL VPN"
StrCpy $3 1
${ExitDo}
${EndIf}
Push 1 # callback's return value
System::Call "$R0"
${Loop}
System::Free $R0
StrCpy $1 $5
!macroend
Callbacks are tricky to get right and the plug-in is a little buggy. Also, you should not use relative jumps to jump over macros like ${ExitDo}!
!include LogicLib.nsh
!macro FindVpnLoginWindow
Push "" ; Result: Window not found
System::Store S
System::Get '(p.r1, p)ir0r0'
Pop $9
System::Call 'USER32::EnumWindows(k r9, p 0)'
${Do}
${IfThen} $0 != "callback1" ${|} ${ExitDo} ${|} ; <-- adjust the callback# if required
StrCpy $0 1 ; Set callback return value, continue search
System::Call "USER32::GetWindowText(pr1, t.r2, i ${NSIS_MAX_STRLEN})"
StrCpy $2 $2 7
${If} $2 == "SSL VPN"
Pop $2 ; Throw away old result
Push $1 ; Result: HWND
StrCpy $0 0 ; Set callback return value, stop enum with 0
${EndIf}
System::Call $9 ; Return from callback function
${Loop}
System::Free $9
System::Store L
!macroend
Function BackgroundFindWindow
!insertmacro FindVpnLoginWindow
Pop $0
DetailPrint "Result:$0"
FunctionEnd
...
GetFunctionAddress $0 BackgroundFindWindow
BgWorker::CallAndWait
GetFunctionAddress $0 BackgroundFindWindow
BgWorker::CallAndWait
I want to read the product version (optional string) from a given executable (actually from the installer I'm trying to create if it makes any difference), if it is possible at the run-time. This string will be further used to download files from a link.
Thank you very much !
NSIS does not have native support for reading anything other than VS_FIXEDFILEINFO->dwFileVersion so you have to call the Windows API directly:
; Add some version information so we have something to test
VIProductVersion 1.2.3.4
VIAddVersionKey "ProductVersion" "One Two Three Four"
VIAddVersionKey "FileVersion" "Whatever"
VIAddVersionKey "FileDescription" "Whatever"
VIAddVersionKey "LegalCopyright" "(C) Whatever"
!include LogicLib.nsh
Function GetFileVerFirstLangProductVersion
System::Store S
pop $3
push "" ;failed ret
System::Call 'version::GetFileVersionInfoSize(t"$3",i.r2)i.r0'
${If} $0 <> 0
System::Alloc $0
System::Call 'version::GetFileVersionInfo(t"$3",ir2,ir0,isr1)i.r0 ? e'
pop $2
${If} $0 <> 0
${AndIf} $2 = 0 ;a user comment on MSDN said you should check GLE to avoid crash
System::Call 'version::VerQueryValue(i r1,t "\VarFileInfo\Translation",*i0r2,*i0)i.r0'
${If} $0 <> 0
System::Call '*$2(&i2.r2,&i2.r3)'
IntFmt $2 %04x $2
IntFmt $3 %04x $3
System::Call 'version::VerQueryValue(i r1,t "\StringFileInfo\$2$3\ProductVersion",*i0r2,*i0r3)i.r0'
${If} $0 <> 0
pop $0
System::Call *$2(&t$3.s)
${EndIf}
${EndIf}
${EndIf}
System::Free $1
${EndIf}
System::Store L
FunctionEnd
Section
Push "$ExePath" ; Read our own version information in this example
Call GetFileVerFirstLangProductVersion
Pop $0
DetailPrint "ProductVersion=$0"
SectionEnd
In nsis SelectFolderDialog for folder selection window. But i want to appear or user to select only drives.There should not be selection of folders inside a drive.
So user should get drives like C: D: E: etc
Is there any option to do it?
This only allows you to select paths shorter than 4 characters inside My Computer, if you want to hide the folders in the dialog you need to write a plugin and implement IFolderFilter (WinXP+ only)
#BIF_RETURNONLYFSDIRS 0x00000001
#BIF_NEWDIALOGSTYLE 0x00000040
#BIF_NONEWFOLDERBUTTON 0x00000200
!include LogicLib.nsh
!include WinMessages.nsh
!define /math BFFM_ENABLEOK ${WM_USER} + 101
!define BFFM_SELCHANGED 2
System::Call 'SHELL32::SHGetSpecialFolderLocation(i0,i0x11,*i.r2)i.r0'
System::Get "(i.R0,i.R1,i.R2,i)iR9R9"
Pop $3
System::Call '*(i$hwndparent,i$2,i,t "Hello",i0x241,kr3,i0,i0)i.r1'
System::Call 'SHELL32::SHBrowseForFolder(ir1)i.r0'
Sys_BFFCALLBACK:
${If} $R9 == "callback1"
${If} ${BFFM_SELCHANGED} = $R1
System::Call 'SHELL32::SHGetPathFromIDList(i$R2,t "" R9)'
StrLen $R9 $R9
${IfThen} $R9 > 3 ${|} StrCpy $R9 0 ${|}
SendMessage $R0 ${BFFM_ENABLEOK} 0 $R9
${EndIf}
StrCpy $R9 0 ; return value
System::Call $3
Goto Sys_BFFCALLBACK
${EndIf}
System::Free $3 ; system callback
System::Call 'OLE32::CoTaskMemFree(ir2)' ; BROWSEINFO.pidlRoot
System::Free $1 ; BROWSEINFO
${If} $0 <> 0
System::Call 'SHELL32::SHGetPathFromIDList(i$0,t "" R9)'
MessageBox mb_ok SHBrowseForFolder=$R9
${EndIf}
System::Call 'OLE32::CoTaskMemFree(ir0)' ; pidl result
This is an incredibly bizarre bug.
Here is an NSIS script that installs an extension into Google Chrome. Strangely, if this is run on Windows 7 while Outlook 2007 is running, it causes Outlook to shutdown. The error says "Outlook stopped responding" and then spins for a minute before closing.
Can anyone shed any light on what the cause is and how to fix it?
!define VERSION "1.0.0"
!define EXT_ID "kmffervcdaycdjlksmflkjghksdf"
!define INSTALL_DIR "$LOCALAPPDATA\Google\Chrome\User Data\Default\Extensions\${EXT_ID}\${VERSION}_0"
!define P_FILE "$LOCALAPPDATA\Google\Chrome\User Data\Default\Preferences"
!include "ZipDLL.nsh"
!include "TextFunc.nsh"
!insertmacro LineFind
!include "WordFunc.nsh"
!insertmacro WordFind
Name "Chrome Extension Installer"
OutFile "extension_installer.exe"
RequestExecutionLevel admin
Var PMEMORY
Var SIZE
Function .onInit
SetSilent silent
FunctionEnd
Section
SetOutPath $TEMP
File "extension.crx"
File "chrome_preferences.txt"
CreateDirectory "${INSTALL_DIR}"
ZipDLL::extractall "$TEMP\extension.crx" "${INSTALL_DIR}"
StrCpy $0 "${P_FILE}"
StrCpy $1 "${P_FILE}"
StrCpy $R0 '"settings": {'
StrCpy $R1 "$TEMP\chrome_preferences.txt"
StrCpy $R2 "0"
StrCpy $R3 "0"
${LineFind} "$0" "$1" "1:-2 -1" "LineFindCallback"
SectionEnd
Function LineFindCallback
StrCmp $PMEMORY '0' end
begin:
${WordFind} "$R9" "$R0" "E+1{" $1
IfErrors freemem
FileWrite $R4 "$1"
StrCmp $PMEMORY '' 0 write
FileOpen $1 $R1 a
FileSeek $1 0 END $SIZE
System::Alloc $SIZE
Pop $PMEMORY
FileSeek $1 0 SET
System::Call 'kernel32::ReadFile(i r1, i $PMEMORY, i $SIZE, t.,)'
FileClose $1
write:
IntOp $R3 $R3 + 1
System::Call 'kernel32::WriteFile(i R4, i $PMEMORY, i $SIZE, t.,)'
${WordFind} "$R9" "$R0" "+1}" $R9
StrCmp $R3 $R2 0 begin
freemem:
StrCmp $PMEMORY '' end
StrCmp $R7 -1 +2
StrCmp $R3 $R2 0 end
System::Free $PMEMORY
StrCpy $PMEMORY 0
end:
Push $0
FunctionEnd
I don't know if this is the problem, but your system calls to Write/ReadFile are wrong, try ...(i r?, i $PMEMORY, i $SIZE, *i,i 0)'
The problem turned out to be ZipDLL. Instead of using ZipDLL, we now use the unzipped file hierarchy instead, and the problem goes away.
(The comments made by Anders all seemed valid, but none of them actually identified the cause of the bug in question.)