From 352f409053c3d144eed4f8bba6d7f76498f5298c Mon Sep 17 00:00:00 2001 From: joostverburg Date: Wed, 12 Nov 2003 12:55:13 +0000 Subject: [PATCH] UpgradeDLL include file, VB6 runtime installation git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3130 212acab6-be3b-0410-9dea-997c60f758d6 --- Docs/src/usefulfunc.but | 2 + Docs/src/usefulinfos.but | 66 ++++++++++++++----- Include/UpgradeDLL.nsh | 136 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+), 17 deletions(-) create mode 100644 Include/UpgradeDLL.nsh diff --git a/Docs/src/usefulfunc.but b/Docs/src/usefulfunc.but index 9e84d6dd..d248535e 100644 --- a/Docs/src/usefulfunc.but +++ b/Docs/src/usefulfunc.but @@ -443,6 +443,8 @@ \H{upgradedll} Upgrade a DLL (macro) +There is also a copy of this macro in the Include folder, so you only have to include UpgradeDLL.nsh to use it. + \c ; Macro - Upgrade DLL File \c ; Written by Joost Verburg \c ; ------------------------ diff --git a/Docs/src/usefulinfos.but b/Docs/src/usefulinfos.but index 94514954..3a22593a 100644 --- a/Docs/src/usefulinfos.but +++ b/Docs/src/usefulinfos.but @@ -80,11 +80,11 @@ If both NoModify and NoRepair are set to 1, the button displays "Remove" instead \H{usefulvb6_runtime} How to install the VB6 runtimes -The best way to install the VB6 runtimes is to use the \R{upgradedll}{UpgradeDLL macro} to upgrade the DLL files, and the \R{addshareddll}{AddSharedDLL macro} when installing the software for the first time to increase the shared DLL count. Define UPGRADEDLL_NOREGISTER before upgrading Stdole2.tlb (and undefine it before upgrading other files). +The best way to install the VB6 runtimes is to use the \R{upgradedll}{UpgradeDLL macro} to upgrade the DLL files and the \R{addshareddll}{AddSharedDLL function} to increment the shared DLL count. Use the Modern UI with a Finish page to ask for a reboot if required or use \R{IfRebootFlag}{IfRebootFlag} and make your own page or messagebox. -You can extract the files from vbrun60sp5.exe using any archiver that supports CAB compression, or if you have installed the latest version on your system, copy the following files from your system directory: +To get the VB6 runtime files, you can extract the files from vbrun60sp5.exe using any archiver that supports CAB compression or, if you have installed the latest version, copy the the files from the System folder. You need the following files: Asycfilt.dll \\ Comcat.dll \\ @@ -93,27 +93,29 @@ Oleaut32.dll \\ Olepro32.dll \\ Stdole2.tlb \\ -During the uninstallation, use \R{unremovesharedll}{un.RemoveSharedDLL} to decrement the shared DLL count, but remove the Delete /REBOOTOK $R1 line, because the shared DLL registration is not reliable enough for such important system files. +During the uninstallation, use the un.DecrementSharedDLL function below to decrement the shared DLL count (never remove the files, because the shared DLL count is not reliable enough for such imporant files). -\c # Don't forget to copy the macro's! +\c !include "UpgradeDLL.nsh" \c -\c !define VBFILESDIR C:\Windows\System -\c # or -\c #!define VBFILESDIR C:\Path\to\where\vbrun60sp5.exe\extracted +\c !define VBFILESDIR "C:\Windows\System" ;Location of VB6 runtime files \c \c Section "Install VB DLLs" +\c \c !insertmacro UpgradeDLL ${VBFILESDIR}\Comcat.dll $SYSDIR\Comcat.dll $SYSDIR \c !insertmacro UpgradeDLL ${VBFILESDIR}\Msvbvm60.dll $SYSDIR\Msvbvm60.dll $SYSDIR \c !insertmacro UpgradeDLL ${VBFILESDIR}\Oleaut32.dll $SYSDIR\Oleaut32.dll $SYSDIR \c !insertmacro UpgradeDLL ${VBFILESDIR}\Olepro32.dll $SYSDIR\Olepro32.dll $SYSDIR +\c \c !define UPGRADEDLL_NOREGISTER \c !insertmacro UpgradeDLL ${VBFILESDIR}\Asycfilt.dll $SYSDIR\Asycfilt.dll $SYSDIR \c !insertmacro UpgradeDLL ${VBFILESDIR}\Stdole2.tlb $SYSDIR\Stdole2.tlb $SYSDIR \c !undef UPGRADEDLL_NOREGISTER -\c # skip shared count increasing if already done once for this application -\c IfFileExists $INSTDIR\myprog.exe skipAddShared +\c +\c ;Only iease DLL count on new installation +\c ;Replace myprog.exe or use another detection method +\c IfFileExists $INSTDIR\myprog.exe skipAddSharedDLL \c Push $SYSDIR\Asycfilt.dll -\c Call AddSharedDLL +\c Call AncrddSharedDLL \c Push $SYSDIR\Comcat.dll \c Call AddSharedDLL \c Push $SYSDIR\Msvbvm60.dll @@ -124,23 +126,53 @@ During the uninstallation, use \R{unremovesharedll}{un.RemoveSharedDLL} to decre \c Call AddSharedDLL \c Push $SYSDIR\Stdole2.tlb \c Call AddSharedDLL -\c skipAddShared: +\c skipAddSharedDLL: +\c \c SectionEnd \c \c Section "Uninstall" +\c \c Push $SYSDIR\Asycfilt.dll -\c Call un.RemoveSharedDLL +\c Call un.DecrementSharedDLL \c Push $SYSDIR\Comcat.dll -\c Call un.RemoveSharedDLL +\c Call un.DecrementSharedDLL \c Push $SYSDIR\Msvbvm60.dll -\c Call un.RemoveSharedDLL +\c Call un.DecrementSharedDLL \c Push $SYSDIR\Oleaut32.dll -\c Call un.RemoveSharedDLL +\c Call un.DecrementSharedDLL \c Push $SYSDIR\Olepro32.dll -\c Call un.RemoveSharedDLL +\c Call un.DecrementSharedDLL \c Push $SYSDIR\Stdole2.tlb -\c Call un.RemoveSharedDLL +\c Call un.DecrementSharedDLL +\c \c SectionEnd +\c +\c Function AddSharedDLL +\c Exch $R1 +\c Push $R0 +\c ReadRegDword $R0 HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 +\c IntOp $R0 $R0 + 1 +\c WriteRegDWORD HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 $R0 +\c Pop $R0 +\c Pop $R1 +\c FunctionEnd +\c +\c Function un.DecrementSharedDLL +\c Exch $R1 +\c Push $R0 +\c ReadRegDword $R0 HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 +\c StrCmp $R0 "" done +\c IntOp $R0 $R0 - 1 +\c IntCmp $R0 0 rk rk uk +\c rk: +\c DeleteRegValue HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 +\c Goto done +\c uk: +\c WriteRegDWORD HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 $R0 +\c done: +\c Pop $R0 +\c Pop $R1 +\c FunctionEnd \H{useful_system_plugin} Calling an external DLL using the System.dll plugin diff --git a/Include/UpgradeDLL.nsh b/Include/UpgradeDLL.nsh new file mode 100644 index 00000000..fcb62369 --- /dev/null +++ b/Include/UpgradeDLL.nsh @@ -0,0 +1,136 @@ +!ifndef UPGRADEDLL_INCLUDED + +!define UPGRADEDLL_INCLUDED + +; Macro - Upgrade DLL File +; Written by Joost Verburg +; ------------------------ +; +; Parameters: +; LOCALFILE - Location of the new DLL file (on the compiler system) +; DESTFILE - Location of the DLL file that should be upgraded (on the user's system) +; TEMPBASEDIR - Directory on the user's system to store a temporary file when the system has +; to be rebooted. +; For Win9x support, this should be on the same volume as the DESTFILE! +; The Windows temp directory could be located on any volume, so you cannot use +; this directory. +; +; Define UPGRADEDLL_NOREGISTER if you want to upgrade a DLL that does not have to be registered. +; +; Note: If you want to support Win9x, you can only use short filenames (8.3). +; +; Example of usage: +; !insertmacro UpgradeDLL "dllname.dll" "$SYSDIR\dllname.dll" "$SYSDIR" +; + +!macro UpgradeDLL LOCALFILE DESTFILE TEMPBASEDIR + + Push $R0 + Push $R1 + Push $R2 + Push $R3 + + ;------------------------ + ;Unique number for labels + + !define UPGRADEDLL_UNIQUE ${__LINE__} + + ;------------------------ + ;Check file and version + + IfFileExists "${DESTFILE}" 0 upgradedll.copy_${UPGRADEDLL_UNIQUE} + + ClearErrors + GetDLLVersionLocal "${LOCALFILE}" $R0 $R1 + GetDLLVersion "${DESTFILE}" $R2 $R3 + IfErrors upgradedll.upgrade_${UPGRADEDLL_UNIQUE} + + IntCmpU $R0 $R2 0 upgradedll.done_${UPGRADEDLL_UNIQUE} upgradedll.upgrade_${UPGRADEDLL_UNIQUE} + IntCmpU $R1 $R3 upgradedll.done_${UPGRADEDLL_UNIQUE} upgradedll.done_${UPGRADEDLL_UNIQUE} \ + upgradedll.upgrade_${UPGRADEDLL_UNIQUE} + + ;------------------------ + ;Let's upgrade the DLL! + + SetOverwrite try + + upgradedll.upgrade_${UPGRADEDLL_UNIQUE}: + !ifndef UPGRADEDLL_NOREGISTER + ;Unregister the DLL + UnRegDLL "${DESTFILE}" + !endif + + ;------------------------ + ;Try to copy the DLL directly + + ClearErrors + StrCpy $R0 "${DESTFILE}" + Call :upgradedll.file_${UPGRADEDLL_UNIQUE} + IfErrors 0 upgradedll.noreboot_${UPGRADEDLL_UNIQUE} + + ;------------------------ + ;DLL is in use. Copy it to a temp file and Rename it on reboot. + + GetTempFileName $R0 "${TEMPBASEDIR}" + Call :upgradedll.file_${UPGRADEDLL_UNIQUE} + Rename /REBOOTOK $R0 "${DESTFILE}" + + ;------------------------ + ;Register the DLL on reboot + + !ifndef UPGRADEDLL_NOREGISTER + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\RunOnce" \ + "Register ${DESTFILE}" '"$SYSDIR\rundll32.exe" "${DESTFILE}",DllRegisterServer' + !endif + + Goto upgradedll.done_${UPGRADEDLL_UNIQUE} + + ;------------------------ + ;DLL does not exist - just extract + + upgradedll.copy_${UPGRADEDLL_UNIQUE}: + StrCpy $R0 "${DESTFILE}" + Call :upgradedll.file_${UPGRADEDLL_UNIQUE} + + ;------------------------ + ;Register the DLL + + upgradedll.noreboot_${UPGRADEDLL_UNIQUE}: + !ifndef UPGRADEDLL_NOREGISTER + RegDLL "${DESTFILE}" + !endif + + ;------------------------ + ;Done + + upgradedll.done_${UPGRADEDLL_UNIQUE}: + + Pop $R3 + Pop $R2 + Pop $R1 + Pop $R0 + + ;------------------------ + ;End + + Goto upgradedll.end_${UPGRADEDLL_UNIQUE} + + ;------------------------ + ;Called to extract the DLL + + upgradedll.file_${UPGRADEDLL_UNIQUE}: + File /oname=$R0 "${LOCALFILE}" + Return + + upgradedll.end_${UPGRADEDLL_UNIQUE}: + + ;------------------------ + ;Restore settings + + SetOverwrite lastused + + !undef UPGRADEDLL_UNIQUE + +!macroend + +!endif \ No newline at end of file