Archive: Newbie question


Newbie question
I'm new to NSIS (couple of days). It seems to be a great tool thus far. I seem to have everything working except for one issue. I'm installing a 32 bit legacy app on Windows 7x64. I cannot get the InstallLib macro to write files to $SYSDIR or "$COMMONFILES\Microsoft Shared\VFP".

I think I have set RequestExecutionLevel and used UAC_RunElevated correctly?? from what I found in the examples and forums. The File statement does succeed in creating a file in the SysWOW64 folder, so $SYSDIR is working for it. It also creates the $INSTDIR folder under Program Files x64 and populates the files. There are no error messages; the $SYSDIR files simply do not get created. I seem to be close but I must be missing something simple - either a setting, system variable, or I may not fully understand the coding order required.

I am listing the code (less uninstall) in hopes that someone can look at it and point me in the right direction.


; Script generated by the HM NIS Edit Script Wizard.

; HM NIS Edit Wizard helper defines
!define PRODUCT_NAME "KOF Data System"
!define PRODUCT_VERSION "1.0"
!define PRODUCT_PUBLISHER "KOF Company"
!define PRODUCT_WEB_SITE "http://www.zakula.com"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\kfMain.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir"

; MUI 1.67 compatible ------
!include "MUI.nsh"

!include LogicLib.nsh

; Administrative priveleges
!include UAC.nsh

; 64 bit compatibility ------
!include x64.nsh ; jz

; DLL/TLB installation routine ------
!include Library.nsh ; jz

; MUI Settings
!define MUI_ABORTWARNING
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"

; Welcome page
!insertmacro MUI_PAGE_WELCOME

; License page
!define MUI_LICENSEPAGE_CHECKBOX
!insertmacro MUI_PAGE_LICENSE "g:\kof_setup_9\License.txt"

; Start menu page
var ICONS_GROUP
!define MUI_STARTMENUPAGE_NODISABLE
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "KOF Data System"
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}"
!insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP

; Instfiles page
!insertmacro MUI_PAGE_INSTFILES

; Finish page
!define MUI_FINISHPAGE_RUN "$INSTDIR\kfMain.exe"
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\ReadMe.txt"
!insertmacro MUI_PAGE_FINISH

; Uninstaller pages
!insertmacro MUI_UNPAGE_INSTFILES

; Language files
!insertmacro MUI_LANGUAGE "English"

; MUI end ------

Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "kfSetup.exe"
InstallDir "$PROGRAMFILES\KOF"
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
BrandingText 'KOF System'
ShowInstDetails show
ShowUnInstDetails show
RequestExecutionLevel none
BGGradient FF0000 0000FF 00FF00
Icon 'g:\kof_Setup_9\kof.ico'
InstProgressFlags 'smooth'
LicenseBkColor '/windows'
WindowIcon on
SetFont Tahoma 10


;;;;;;;;; FUNCTION .ONINIT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function .onInit ; jz

; Try to setup admin priveleges for install process (COPIED EXAMPLE)
uac_tryagain:
!insertmacro UAC_RunElevated
#MessageBox mb_TopMost "0=$0 1=$1 2=$2 3=$3"
${Switch} $0
${Case} 0
${IfThen} $1 = 1 ${|} Quit ${|} ;we are the outer process, the inner process has done its work, we are done
${IfThen} $3 <> 0 ${|} ${Break} ${|} ;we are admin, let the show go on
${If} $1 = 3 ;RunAs completed successfully, but with a non-admin user
MessageBox mb_IconExclamation|mb_TopMost|mb_SetForeground "This installer requires admin access, try again" /SD IDNO IDOK uac_tryagain IDNO 0
${EndIf}
;fall-through and die
${Case} 1223
MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "This installer requires admin privileges, aborting!"
Quit
${Case} 1062
MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Logon service not running, aborting!"
Quit
${Default}
MessageBox mb_IconStop|mb_TopMost|mb_SetForeground "Unable to elevate , error $0"
Quit
${EndSwitch}


; Set up and display splash screen w/fade-in
SetOutPath $TEMP
File /oname=$PLUGINSDIR\SplashTmp.bmp "g:\kof_setup_9\KOF_SetupSplash1.bmp"
advsplash::show 1000 850 500 -1 $PLUGINSDIR\SplashTmp


; To determine the system folders (32 bit or 64 bit) at runtime
${EnableX64FSRedirection}
StrCpy $INSTDIR "$PROGRAMFILES\KOF"
FunctionEnd
;;;;;;;;; FUNCTION .ONINIT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;; FUNCTION .ONGUIEND ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Function .onGuiEnd ; jz
; Run PostgreSql ODBC 8.3 install application, and then delete it
ExecWait '"msiexec" /i "$INSTDIR\psql_odbc_8_3.msi"' ; PostgreSQL ODBC installer
;Delete "$INSTDIR\psql_odbc_8_3.msi"

; If Chosen by user, display the readme file
MessageBox MB_YESNO|MB_ICONQUESTION "Do you wish to view the ReadMe file now?" IDNO false
!system '"$WINDIR\notepad.exe" "$INSTDIR\ReadMe.txt"'
false:

MessageBox MB_YESNO|MB_ICONQUESTION "The computer must be rebooted for settings to take effect. Do you wish to reboot your computer now?" IDNO false2
Reboot
false2:
FunctionEnd
;;;;;;;;; FUNCTION .ONGUIEND ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;;;;;;; SECTION SEC01 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Section "MainSection" SEC01
SetOverwrite ifnewer

; Copy into $INSTDIR
SetOutPath "$INSTDIR"

; Copy app-specific files
File "g:\kof_setup_9\kfMain.exe"
File "g:\kof_setup_9\Config.fpw"
File "g:\kof_setup_9\AppStart.app"
; Dummy app to trigger "get updated build" process
File "g:\kof_setup_9\kf0000.app"
File "g:\kof_setup_9\AppInfo.ini"
File "g:\kof_setup_9\ReportOutput.app"
File "g:\kof_setup_9\ReportPreview.app"
File "g:\kof_setup_9\ReportBuilder.app"
File "g:\kof_setup_9\FoxTools.fll"
File "g:\kof_setup_9\MD5.fll"
File "g:\kof_setup_9\FoxUser.dbf"
File "g:\kof_setup_9\FoxUser.fpt"
File "g:\kof_setup_9\vfpAlert.exe"

; Copy necessary ODBC driver installation package
File "g:\kof_setup_9\PostgresOdbcDriver\psql_odbc_8_3.msi"

; Copy files needed for Dazzle interface is to be shipping computer
CreateDirectory "$INSTDIR\Dazzle"
SetOutPath "$INSTDIR\Dazzle"
File "g:\kof_setup_9\Dazzle\Dazzle_BoundPrint.lyt"
File "g:\kof_setup_9\Dazzle\Dazzle_FirstClass.lyt"
File "g:\kof_setup_9\Dazzle\Dazzle_MediaMail.lyt"
File "g:\kof_setup_9\Dazzle\Dazzle_ParcelPost.lyt"
File "g:\kof_setup_9\Dazzle\Dazzle_PriorityMail.lyt"
File "g:\kof_setup_9\Dazzle\Dazzle_APO_FPO_ShipLabel.lyt"
File "g:\kof_setup_9\Dazzle\Dazzle_Lg_Pri_Intl_ShipLbl.lyt"
File "g:\kof_setup_9\Dazzle\KofPackage1.lyt"
File "g:\kof_setup_9\Dazzle\DazzleAddressCodes.txt"
File "g:\kof_setup_9\Dazzle\DazzlePostalServices.txt"
File "g:\kof_setup_9\Dazzle\KofDazzle_ReadMe.txt"

; Copy into $INSTDIR\BarCode_Scanner
CreateDirectory "$INSTDIR\BarCode_Scanner"
SetOutPath "$INSTDIR\BarCode_Scanner"
File "g:\kof_setup_9\BarCode_Scanner\Free3of9.txt"
File "g:\kof_setup_9\BarCode_Scanner\kf_ScannerSetup.txt"
File "g:\kof_setup_9\BarCode_Scanner\Xi2000_Manual.pdf"
File "g:\kof_setup_9\BarCode_Scanner\Xi2000_Spec.pdf"

; Copy into $FONTS
SetOutPath "$FONTS"
File "g:\kof_setup_9\BarCode_Scanner\Free3of9.ttf"
File "g:\kof_setup_9\BarCode_Scanner\Fre3of9x.ttf"

SetOutPath "$SYSDIR"
; Try to use a straight file write to sysdir
File "g:\kof_setup_9\TestSysDirFile.txt"

; Install in $COMMONFILES or $SYSDIR
!insertmacro InstallLib DLL SHARED REBOOT_PROTECTED "g:\kof_setup_9\MsVcr71.dll" $SYSDIR $COMMONFILES

CreateDirectory "$COMMONFILES\Microsoft Shared\VFP"
!insertmacro InstallLib DLL SHARED REBOOT_PROTECTED "g:\kof_setup_9\GdiPlus.dll" "$COMMONFILES\Microsoft Shared\VFP" $COMMONFILES

!insertmacro InstallLib REGDLL SHARED REBOOT_PROTECTED "g:\kof_setup_9\vfp9R.dll" "$COMMONFILES\Microsoft Shared\VFP" $COMMONFILES
!insertmacro InstallLib REGDLL SHARED REBOOT_PROTECTED "g:\kof_setup_9\vfp9T.dll" "$COMMONFILES\Microsoft Shared\VFP" $COMMONFILES
!insertmacro InstallLib DLL SHARED REBOOT_PROTECTED "g:\kof_setup_9\vfp9Renu.dll" "$COMMONFILES\Microsoft Shared\VFP" $COMMONFILES

!insertmacro InstallLib REGEXE SHARED REBOOT_PROTECTED "g:\kof_setup_9\FoxHHelp9.exe" "$COMMONFILES\Microsoft Shared\VFP" $COMMONFILES
!insertmacro InstallLib DLL SHARED REBOOT_PROTECTED "g:\kof_setup_9\FoxHHelpPs9.dll" "$COMMONFILES\Microsoft Shared\VFP" $COMMONFILES

; Already available in windows
;!insertmacro InstallLib DLL SHARED REBOOT_PROTECTED "g:\kof_setup_9\MsXml3.dll" $SYSDIR $COMMONFILES
;!insertmacro InstallLib DLL SHARED REBOOT_PROTECTED "g:\kof_setup_9\MsXml3r.dll" $SYSDIR $COMMONFILES

!insertmacro InstallLib DLL SHARED REBOOT_PROTECTED "g:\kof_setup_9\MsXml3a.dll" $SYSDIR $COMMONFILES
!insertmacro InstallLib REGDLL SHARED REBOOT_PROTECTED "g:\kof_setup_9\MsXml4.dll" $SYSDIR $COMMONFILES
!insertmacro InstallLib REGDLL SHARED REBOOT_PROTECTED "g:\kof_setup_9\MsXml4r.dll" $SYSDIR $COMMONFILES

!insertmacro InstallLib REGDLL SHARED REBOOT_PROTECTED "g:\kof_setup_9\Filer.dll" "$COMMONFILES\Microsoft Shared\VFP" $COMMONFILES
!insertmacro InstallLib DLL NOTSHARED REBOOT_PROTECTED "g:\kof_setup_9\DibApi32.dll" $INSTDIR $COMMONFILES

; Create the Shortcuts
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
SetShellVarContext all
CreateDirectory "$SMPROGRAMS\KOF Data System"
CreateShortCut "$SMPROGRAMS\KOF Data System\KOF.lnk" "$INSTDIR\kfMain.exe"
CreateShortCut "$DESKTOP\KOF.lnk" "$INSTDIR\kfMain.exe"
CreateShortCut "$QUICKLAUNCH\KOF.lnk" "$INSTDIR\kfMain.exe"
SetShellVarContext current
!insertmacro MUI_STARTMENU_WRITE_END

SectionEnd
;;;;;;; SECTION SEC01 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


In your post, I assume you meant Program Files (x86)? You need to use ${DisableX64FSRedirection} to write to system32/Program Files. Also I would recommend using MUI2.nsh over MUI.nsh (uses nsDialogs and is therefore faster).

Your script isn't too big but in future please attach the script or use pastebin.

Stu


Hi Stu,

Thanks, I did mean x86.

I changed
${EnableX64FSRedirection}
to
${DisableX64FSRedirection}
but the 32 bit files still do not show up in the system directory (SysWoW64?) with InstallLib. Is .onInit the right place for this?

Thanks for the prompt response.

Jeff


OK sorry if you want to install to SysWOW64 then you do not need to enable or disable file system redirection. Windows will redirect to SysWOW64 anyway. If it is not working then you don't have access to the folder. You need to use RequestExecutionLevel admin.

Edit: Also .onInit would not be the correct place as the Wow64EnableWow64FsRedirection API only works for the current thread. Sections run under a new thread and therefore you'd need to use Wow64EnableWow64FsRedirection again.

Stu


Hi Stu,

I'm back again. I cannot seem to get get this thing to work. I've tried what you suggested and a host of other things. The InstallLib macro simply refuses to install any files in any system folders or any "common files" subfolders. The File command has no problem writing these dlls to the folders where InstallLib fails.

What is the special secret to making InstallLib work? Do I need to use SetOutPath to point to the target directory even though the target directory is one of the parameters? Is my syntax somehow incorrect? Do I need to use the File command to copy the file first? How do I know it got registered, etc?

I have attached my code so you can see the InstallLib syntax. I must be doing something really stupid, but I can't seem to see what. This is the only problem I've had, but without this functionality there is no install.

Jeff


Sorry, I forgot to attach on the last post.

Jeff


Do you need to use the UAC plugin? I've been doing fine with RequestionExecutionLevel admin on Windows 7 32/64.

I recommend just writing a basic script which does the bare minimum until you can find out the problem.

Stu


No problem. I'll comment it out and try it.

Also, I'm just about coded up to use the File command to create the files and RegDLL to register them. Is that a feasible way to do the same thing?

Jeff


It depends on the library. RegDll is the same as using regsvr32 /s (but does not depend on it).

Stu


Hi Stu,

I've been out of the office for a while. The presence of the UAC plugin didn't affect my problem either way. I did, when I got back, get things working in a round-about way. I found a prewritten installer for all the VFP support libraries that I needed. I called that installer from an ExecWait statement. I preceded that with instructions on a notepad window called from ExecWait. I followed that with a .msi to install odbc drivers via ExecWait.

It's not thrilling, but it works. I would still like to know why InstallLib fails for the next time that I need to do something similar.

Thanks for the effort,

Jeff


Notepad window? If you mean a console window you can hide those using nsExec.

Stu


Well, actually it is a Notepad window. I don't need to really hide. I'm using an external installer (exe) for some of the support libraries during the middle of the NSIS install. But it requires to make a few selections on its start screen. So I use ExecWait to display the Notepad window with instructions on what to select, and it informs the user that the install process will continue when he closes the instruction window.

But I have another question. In my script I would like to abstract the path where the compiler finds the source files. This way I could put everything on the local server where there is easy access to the installation executable. Also, edits and recompiles of the script that might be needed will always be where they are going to be used, eliminating the need to remember to copy any files when any change occurs.

Can I just copy my current ${NSISDIR} tree to the server? Will everything work there from any computer, or is an install required because of support files or reg keys? Then I can add my source folders to that tree and and use ${NSISDIR} to find everything. Also, $EXEPATH and $EXEDIR do not presently work. Is this because I move the exe file after it gets compiled to the server where it gets run from desktop computers as a program on a mapped network drive? In fact, maybe this is why InstallLib does not work at runtime?