User:Dad
From WPKG | Open Source Software Deployment and Distribution
Daniel Dehennin
Contents |
[edit] Using unattended script
I'm using unattened script from Rainer Meier with some modifications:
- Engine is unattended.cmd
- Install scripts are called install.cmd
- Uninstall scripts are called remove.cmd
- Add msiupdate installtype
- Execute start commande with /D"%INSTALLER_PATH%": if the %INSTALL_CMD% is located in a subdirectory it may need to locate files relativelly to its path.
- Automatically call pre/post-install/remove scripts:
- preinstall.cmd/postinstall.cmd/preremove.cmd/postremove.cmd in installer path
- preinstall.cmd/postinstall.cmd/preremove.cmd/postremove.cmd in unattended path
- %INSTALL_CMD%-preinstall.cmd/%INSTALL_CMD%-postinstall.cmd/%INSTALL_CMD%-preremove.cmd/%INSTALL_CMD%-postremove.cmd
[edit] install.cmd
@echo off REM Do not export variables SETLOCAL set PROGRAM_NAME=Application REM Command to run set CMD32=installer.exe set CMD64=%CMD32% set CMD_PATH=%~dp0 set CMD_OPTS=/SILENT REM Unattended installer set INSTALLER=unattended.cmd set INSTALLER_TYPE=custominstall set INSTALLER_LOC=%~dp0 REM OS specific path/CMD REM WARNING: %ProgramFiles(x86)% misclose blocs REM use dos function to bypass DOS parser limitation REM :ospath REM REM ver | find "version 5.1" > NUL && ( REM SET CMD_PATH=%CMD_PATH%winxp REM SET CMD_32=install-xp-32.exe REM SET CMD_64=install-xp-64.exe REM ) REM REM ver | find "version 6.0" > NUL && ( REM SET CMD_PATH=%CMD_PATH%winvista REM SET CMD_32=install-vista-32.exe REM SET CMD_64=install-vista-64.exe REM ) REM REM ver | find "version 6.1" > NUL && ( REM SET CMD_PATH=%CMD_PATH%win7 REM SET CMD_32=install-7-32.exe REM SET CMD_64=install-7-64.exe REM ) :install echo Installing %PROGRAM_NAME% call "%INSTALLER_LOC%%INSTALLER%" %INSTALLER_TYPE% "%CMD32%" "%CMD64%" "%CMD_PATH%" "%CMD_OPTS%" set EXIT_CODE=%ERRORLEVEL% :end exit /B %EXIT_CODE% REM End of local variables ENDLOCAL REM Local Variables: REM mode: cmd REM comment-start: "REM " REM comment-end: "" REM End:
[edit] remove.cmd
@echo off REM Do not export variables SETLOCAL set PROGRAM_NAME=Program REM 32/64 bit PATH IF "%ProgramFiles(x86)%" NEQ "" ( call :64bits ) else ( call :32bits ) REM Command to run set CMD32=uninstaller.exe set CMD64=%CMD32% set CMD_PATH=%PROG_PATH%\%PROGRAM_NAME% set CMD_OPTS=/S REM Unattended uninstaller set INSTALLER=unattended.cmd set INSTALLER_TYPE=customuninstall set INSTALLER_LOC=%~dp0 :remove echo Removing %PROGRAM_NAME% call "%INSTALLER_LOC%%INSTALLER%" %INSTALLER_TYPE% "%CMD32%" "%CMD64%" "%CMD_PATH%" "%CMD_OPTS%" set EXIT_CODE=%ERRORLEVEL% :end exit /B %EXIT_CODE% :32bits SET PROG_PATH=%ProgramFiles% GOTO :EOF :64bits SET PROG_PATH=%ProgramFiles(x86)% GOTO :EOF REM End of local variables ENDLOCAL REM Local Variables: REM mode: cmd REM comment-start: "REM " REM comment-end: "" REM End:
[edit] unattended.cmd
The engine doing the hard work
@echo off REM Usage: REM unattended.cmd <type> <32-bit-installer> <64-bit-installer> REM [installer-location [custom-options]] REM where type is one of REM msiinstall Install the given MSI package REM msiupdate Update the given MSP package REM msiuninstall Uninstall the given MSI package REM install4j Install4J setup REM innoinstall Inno setup installer REM innouninstall Inno setup uninstaller REM installshield Install shield REM nsis Nullsoft install system (NSIS) REM custominstall Custom installer - options required in this case REM customuninstall Custom installer - options required in this case REM 32-bit-installer Full file name (including extension) of 32-bit installer REM 64-bit-installer Full file name (including extension) of 64-bit installer REM installer-location Path where the installers are stored, if empty assumes REM directory where install.cmd is REM custom-options Replace the default installer options with the ones given REM Do not export variables SETLOCAL REM Global variables set INSTALL_CMD= set EXIT_CODE=0 REM Get command type set TYPE=%~1 REM Get 32-bit installer name set CMD32=%~2 REM Get 64-bit installer name set CMD64=%~3 REM get file path set INSTALLER_PATH=%~4 REM get unattended path set SCRIPTS_PATH=%~dp0 set OPTIONS= if not "%~5" == "" ( set OPTIONS=%~5 ) REM Detect which system is used if not "%ProgramFiles(x86)%" == "" goto 64bit goto 32bit REM ########################################################################## REM 64-bit system detected REM ########################################################################## :64bit REM Determine 64-bit installer to be used echo 64-bit system detected. REM set INSTALLER64= if not "%CMD64%" == "" ( set INSTALLER64=%CMD64% ) else ( REM Use 32-bit installer if available, no 64-bit installer available. if not "%CMD32%" == "" ( echo Using 32-bit installer, no 64-bit installer specified. set INSTALLER64=%CMD32% ) else ( echo Neither 64-bit nor 32-bit installer specified. Exiting. goto usage ) ) set INSTALL_CMD=%INSTALLER_PATH%%INSTALLER64% goto installerselection REM ########################################################################## REM 32-bit system detected REM ########################################################################## :32bit REM Determine 32-bit installer to be used echo 32-bit system detected. set INSTALLER32= if not "%CMD32%" == "" ( set INSTALLER32=%CMD32% ) else ( echo No 32-bit installer specified. Exiting. exit /B 96 ) set INSTALL_CMD=%INSTALLER_PATH%%INSTALLER32% REM ########################################################################## REM select installer/uninstaller system with pre-install/remove REM ########################################################################## :installerselection if /i "%TYPE%" == "msiuninstall" goto preremove if /i "%TYPE%" == "innouninstall" goto preremove if /i "%TYPE%" == "customuninstall" goto preremove :preinstall REM pre-install if exist "%INSTALLER_PATH%preinstall.cmd" ( call "%INSTALLER_PATH%preinstall.cmd" ) else ( if exist "%SCRIPTS_PATH%preinstall.cmd" ( call "%SCRIPTS_PATH%preinstall.cmd" ) else ( if exist "%INSTALL_CMD%-preinstall.cmd" ( call "%INSTALL_CMD%-preinstall.cmd" ) ) ) goto checkinstaller :preremove REM pre-install if exist "%INSTALLER_PATH%preremove.cmd" ( call "%INSTALLER_PATH%preremove.cmd" ) else ( if exist "%SCRIPTS_PATH%preremove.cmd" ( call "%SCRIPTS_PATH%preremove.cmd" ) else ( if exist "%INSTALL_CMD%-preremove.cmd" ( call "%INSTALL_CMD%-preremove.cmd" ) ) ) :checkinstaller REM Check if installer is valid if not exist "%INSTALL_CMD%" ( echo Installer "%INSTALL_CMD%" cannot be found! Exiting. exit /B 97 ) if /i "%TYPE%" == "msiinstall" goto msiinstaller if /i "%TYPE%" == "msiupdate" goto msiupdate if /i "%TYPE%" == "install4j" goto install4j if /i "%TYPE%" == "innoinstall" goto innoinstaller if /i "%TYPE%" == "installshield" goto installshieldinstaller if /i "%TYPE%" == "nsis" goto nsisinstaller if /i "%TYPE%" == "custominstall" goto custominstaller if /i "%TYPE%" == "msiuninstall" goto msiuninstaller if /i "%TYPE%" == "innouninstall" goto innouninstaller if /i "%TYPE%" == "customuninstall" goto customuninstaller goto usage :msiinstaller echo Installing "%INSTALL_CMD%" start /wait "Software installation" /D"%INSTALLER_PATH%" msiexec /qn /norestart /i "%INSTALL_CMD%" %OPTIONS% set EXIT_CODE=%ERRORLEVEL% goto postinstall :msiupdate echo Updating "%INSTALL_CMD%" start /wait "Software update" /D"%INSTALLER_PATH%" msiexec /qn /norestart /update "%INSTALL_CMD%" %OPTIONS% set EXIT_CODE=%ERRORLEVEL% goto postinstall :msiuninstaller echo Uninstalling "%INSTALL_CMD%" start /wait "Software uninstallation" /D"%INSTALLER_PATH%" msiexec /qn /norestart /x "%INSTALL_CMD%" %OPTIONS% set EXIT_CODE=%ERRORLEVEL% goto postremove :install4j echo Installing "%INSTALL_CMD%" start /wait "Software installation" /D"%INSTALLER_PATH%" "%INSTALL_CMD%" -q %OPTIONS% set EXIT_CODE=%ERRORLEVEL% goto postinstall :innoinstaller echo Installing "%INSTALL_CMD%" start /wait "Software installation" /D"%INSTALLER_PATH%" "%INSTALL_CMD%" /silent /verysilent /norestart /sp- %OPTIONS% set EXIT_CODE=%ERRORLEVEL% goto postinstall :innouninstaller echo Uninstalling "%INSTALL_CMD%" start /wait "Software uninstallation" /D"%INSTALLER_PATH%" "%INSTALL_CMD%" /silent /verysilent /norestart /sp- %OPTIONS% set EXIT_CODE=%ERRORLEVEL% goto postremove :installshieldinstaller echo Installing "%INSTALL_CMD%" start /wait "Software installation" /D"%INSTALLER_PATH%" "%INSTALL_CMD%" /s %OPTIONS% set EXIT_CODE=%ERRORLEVEL% goto postinstall :nsisinstaller echo Installing "%INSTALL_CMD%" start /wait "Software installation" /D"%INSTALLER_PATH%" "%INSTALL_CMD%" /S %OPTIONS% set EXIT_CODE=%ERRORLEVEL% goto postinstall :custominstaller if "%OPTIONS%" == "" goto usage echo Installing "%INSTALL_CMD%" start /wait "Software installation" /D"%INSTALLER_PATH%" "%INSTALL_CMD%" %OPTIONS% set EXIT_CODE=%ERRORLEVEL% goto postinstall :customuninstaller if "%OPTIONS%" == "" goto usage echo Uninstalling "%INSTALL_CMD%" start /wait "Software uninstallation" /D"%INSTALLER_PATH%" "%INSTALL_CMD%" %OPTIONS% set EXIT_CODE=%ERRORLEVEL% goto postremove :usage echo Usage: echo "%~nx0 <type> <32-bit-installer> <64-bit-installer> [installer-location [custom-options]]" echo where type is one of echo msiinstall Install the given MSI package echo msiupdate Update the given MSP package echo msiuninstall Uninstall the given MSI package echo install4j Install4J setup echo innoinstall Inno setup installer echo innouninstall Inno setup uninstaller echo installshield Install shield echo nsis Nullsoft install system (NSIS) echo custominstall Custom installer - options required in this case echo customuninstall Custom installer - options required in this case echo 32-bit-installer Full file name (including extension) of 32-bit installer echo 64-bit-installer Full file name (including extension) of 64-bit installer echo installer-location Path where the installers are stored, if empty assumes echo directory where install.cmd is echo custom-options Replace the default installer options with the ones given exit /B 99 :postinstall REM post-install if exist "%INSTALLER_PATH%postinstall.cmd" ( call "%INSTALLER_PATH%postinstall.cmd" ) else ( if exist "%SCRIPTS_PATH%postinstall.cmd" ( call "%SCRIPTS_PATH%postinstall.cmd" ) else ( if exist "%INSTALL_CMD%-postinstall.cmd" ( call "%INSTALL_CMD%-postinstall.cmd" ) ) ) goto end :postremove REM post-remove if exist "%INSTALLER_PATH%postremove.cmd" ( call "%INSTALLER_PATH%postremove.cmd" ) else ( if exist "%SCRIPTS_PATH%postremove.cmd" ( call "%SCRIPTS_PATH%postremove.cmd" ) else ( if exist "%INSTALL_CMD%-postremove.cmd" ( call "%INSTALL_CMD%-postremove.cmd" ) ) ) :end exit /B %EXIT_CODE% REM End of local variables ENDLOCAL REM Local Variables: REM mode: cmd REM comment-start: "REM" REM comment-end: "" REM End:
[edit] application layout
The basic layout of an application is the following:
<Application> ├── <version prod> │ ├── <installer x32> │ ├── <insaller x64> │ ├── install.cmd │ ├── postinstall.cmd │ ├── remove.cmd │ └── unattended.cmd ├── <version test> │ ├── <insaller x32> │ ├── <insaller x64> │ ├── install.cmd │ ├── postinstall.cmd │ ├── remove.cmd │ └── unattended.cmd ├── install.cmd <----- call <version prod>/install.cmd └── remove.cmd <----- call <version prod>/remove.cmd
The top level install.cmd and remove.cmd only call what I define the version in production. This permit to have static link to install something.
├── 7zip │ ├── 9.13 │ │ ├── 7z913.msi │ │ ├── 7z913-x64.msi │ │ ├── 7zip.reg │ │ ├── install.cmd │ │ ├── postinstall.cmd │ │ ├── remove.cmd │ │ └── unattended.cmd │ ├── 9.17 │ │ ├── 7z917.msi │ │ ├── 7z917-x64.msi │ │ ├── 7zip.reg │ │ ├── install.cmd │ │ ├── postinstall.cmd │ │ ├── remove.cmd │ │ └── unattended.cmd │ ├── install.cmd │ └── remove.cmd ├── adobe │ ├── flash │ │ ├── 10.1 │ │ │ ├── ie │ │ │ │ ├── install.cmd │ │ │ │ ├── install_flash_player_10_active_x.msi │ │ │ │ ├── remove.cmd │ │ │ │ └── unattended.cmd │ │ │ └── mozilla │ │ │ ├── install.cmd │ │ │ ├── install_flash_player_10_plugin.msi │ │ │ ├── remove.cmd │ │ │ └── unattended.cmd │ │ ├── install.cmd │ │ └── remove.cmd │ └── reader │ ├── 9.3.0 │ │ ├── acroread.msi │ │ ├── data1.cab │ │ ├── install.cmd │ │ ├── postinstall.cmd │ │ ├── postremove.cmd │ │ ├── remove.cmd │ │ └── unattended.cmd │ ├── 9.3.2 │ │ ├── adberdrupd932_all_incr.msp │ │ ├── install.cmd │ │ ├── postinstall.cmd │ │ ├── postremove.cmd │ │ ├── preinstall.cmd │ │ ├── remove.cmd │ │ └── unattended.cmd │ ├── 9.3.4 │ │ └── AdbeRdrUpd934_all_incr.msp │ ├── 9.4.0 │ │ ├── acroread.msi │ │ ├── data1.cab │ │ ├── install.cmd │ │ ├── postinstall.cmd │ │ ├── postremove.cmd │ │ ├── remove.cmd │ │ └── unattended.cmd │ ├── install.cmd │ └── remove.cmd ├── template <-- template source │ ├── install.cmd │ ├── postinstall.cmd │ ├── postremove.cmd │ ├── remove.cmd │ └── unattended.cmd [...]
Each version directory has a copy of the unattended.cmd engine, they are autonomous, I can copy each one on an USB key and use it directly.
NB: The template source is the place where I update unattended.cmd, I distribute it in each folder with the following (linux) command:
moi@work:~$ find . -type f -name 'unattended.cmd' -exec cp -f template/unattended.cmd {} \;
[edit] Example with adobe reader 9.4.0
[edit] XML package
<?xml version='1.0' encoding='utf-8'?> <packages> <package id='adobe-reader-9' name='Adobe Reader 9' revision='9.4.0.1' reboot='false' priority='100'> <check type='uninstall' condition='exists' path='Adobe Reader 9.4.0 - Français'/> <check type='logical' condition='or'> <check type='file' condition='versiongreaterorequal' path='%ProgramFiles%\Adobe\Reader 9.0\Reader\Acrord32.exe' value='9.4.0.195'/> <check type='file' condition='versiongreaterorequal' path='%ProgramFiles(x86)%\Adobe\Reader 9.0\Reader\Acrord32.exe' value='9.4.0.195'/> </check> <install cmd='%SOFTWARE%\adobe\reader\9.4.0\install.cmd'/> <upgrade cmd='%SOFTWARE%\adobe\reader\9.4.0\install.cmd'/> <remove cmd='%SOFTWARE%\adobe\reader\9.4.0\remove.cmd'/> </package> </packages>
[edit] %SOFTWARE%\adobe\reader\install.cmd
@echo off REM Do not export variables SETLOCAL set CMD_PATH=%~dp0 set APPLI_VERSION=9.4.0 :install call "%CMD_PATH%\%APPLI_VERSION%\install.cmd" set EXIT_CODE=%ERRORLEVEL% :end exit /B %EXIT_CODE% REM End of local variables ENDLOCAL REM Local Variables: REM mode: cmd REM comment-start: "REM " REM comment-end: "" REM End:
[edit] %SOFTWARE%\adobe\reader\remove.cmd
@echo off REM Do not export variables SETLOCAL set CMD_PATH=%~dp0 set APPLI_VERSION=9.4.0 :remove call "%CMD_PATH%\%APPLI_VERSION%\remove.cmd" set EXIT_CODE=%ERRORLEVEL% :end exit /B %EXIT_CODE% REM End of local variables ENDLOCAL REM Local Variables: REM mode: cmd REM comment-start: "REM " REM comment-end: "" REM End:
[edit] %SOFTWARE%\adobe\reader\9.4.0\install.cmd
@echo off REM Do not export variables SETLOCAL set PROGRAM_NAME=Acrobat Reader 9.4.0 REM Command to run set CMD32=acroread.msi set CMD64=%CMD32% set CMD_PATH=%~dp0 set CMD_OPTS=/qn /norestart ALLUSERS=2 EULA_ACCEPT=YES SUPPRESS_APP_LAUNCH=YES AgreeToLicense=YES ENABLE_CACHE=NO REM Unattended installer set INSTALLER=unattended.cmd set INSTALLER_TYPE=msiinstall set INSTALLER_LOC=%~dp0 :install echo Installing %PROGRAM_NAME% call "%INSTALLER_LOC%%INSTALLER%" %INSTALLER_TYPE% "%CMD32%" "%CMD64%" "%CMD_PATH%" "%CMD_OPTS%" set EXIT_CODE=%ERRORLEVEL% :end exit /B %EXIT_CODE% REM End of local variables ENDLOCAL REM Local Variables: REM mode: cmd REM comment-start: "REM " REM comment-end: "" REM End:
[edit] %SOFTWARE%\adobe\reader\9.4.0\postinstall.cmd
@echo off REM Do not export variables SETLOCAL REM 32/64 bit PATH IF "%ProgramFiles(x86)%" NEQ "" ( call :64bits ) else ( call :32bits ) REM Adobe Reader registery hive SET READER_REG_PATH=%SOFT_PATH%\Adobe Reader\9.0 REM Adobe Reader program path SET READER_PROG_PATH=%PROG_PATH%\Adobe\Reader 9.0 REM Win7 ver | find "version 6.1" 2>NUL > NUL && ( SET AllUsersDesktop=%PUBLIC%\Desktop SET UserDesktop=%UserProfile%\Desktop ) || ( REM Francais/English net localgroup Administrateurs 2> NUL > NUL && ( SET AllUsersDesktop=%AllUsersProfile%\Bureau SET UserDesktop=%UserProfile%\Bureau ) || ( SET AllUsersDesktop=%AllUsersProfile%\Desktop SET UserDesktop=%UserProfile%\Desktop ) ) echo Remove Desktop Shortcut %ComSpec% /c del /F /Q "%AllUsersDesktop%\Adobe Reader*.lnk" 2> NUL > NUL %ComSpec% /c del /F /Q "%UserDesktop%\Adobe Reader*.lnk" 2> NUL > NUL echo Disable EULA reg add "%READER_REG_PATH%\AdobeViewer" /v EULA /t REG_DWORD /d "00000001" /f 2> NUL > NUL reg add "%READER_REG_PATH%\AdobeViewer" /v Launched /t REG_DWORD /d "00000001" /f 2> NUL > NUL echo Disable Beyong reg add "%READER_REG_PATH%\Downtown" /v bDontShowAtLaunch /t REG_DWORD /d "00000001" /f 2> NUL > NUL echo Disable going online reg add "%READER_REG_PATH%\Downtown" /v GoOnline /t REG_DWORD /d "00000000" /f 2> NUL > NUL echo Disable Speed Launcher reg delete "%RUN_PATH%" /v "Adobe Reader Speed Launcher" /f 2> NUL > NUL REM FIXME with 64 bit use %ProgramFiles(x86)% ? echo Turn off automatic update move /Y "%READER_PROG_PATH%\Reader\plug_ins\updater.*" "%READER_PROG_PATH%\Reader\Optional" 2> NUL > NUL echo Disable Adobe ARM reg delete "%RUN_PATH%" /v "Adobe ARM" /f 2> NUL > NUL :end exit /B %ERRORLEVEL% :32bits SET SOFT_PATH=HKLM\SOFTWARE\ SET RUN_PATH=HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run SET PROG_PATH=%ProgramFiles% GOTO :EOF :64bits SET SOFT_PATH=HKLM\Software\Wow6432Node\ SET RUN_PATH=HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run SET PROG_PATH=%ProgramFiles(x86)% GOTO :EOF REM End of local variables ENDLOCAL REM Local Variables: REM mode: cmd REM comment-start: "REM " REM comment-end: "" REM End:
[edit] %SOFTWARE%\adobe\reader\9.4.0\remove.cmd
@echo off REM Do not export variables SETLOCAL set PROGRAM_NAME=Acrobat Reader 9.4.0 REM Command to run set CMD32=acroread.msi set CMD64=%CMD32% set CMD_PATH=%~dp0 set CMD_OPTS= REM Unattended uninstaller set INSTALLER=unattended.cmd set INSTALLER_TYPE=msiuninstall set INSTALLER_LOC=%~dp0 :remove echo Removing %PROGRAM_NAME% call "%INSTALLER_LOC%%INSTALLER%" %INSTALLER_TYPE% "%CMD32%" "%CMD64%" "%CMD_PATH%" "%CMD_OPTS%" set EXIT_CODE=%ERRORLEVEL% :end exit /B %EXIT_CODE% REM End of local variables ENDLOCAL REM Local Variables: REM mode: cmd REM comment-start: "REM " REM comment-end: "" REM End:
[edit] %SOFTWARE%\adobe\reader\9.4.0\postremove.cmd
@echo off REM Do not export variables SETLOCAL REM 32/64 bit PATH IF "%ProgramFiles(x86)%" NEQ "" ( call :64bits ) else ( call :32bits ) REM Adobe Reader program path SET READER_PROG_PATH=%PROG_PATH%\Adobe\Reader 9.0 REM Remove remaining directories rd /S /Q "%READER_PROG_PATH%" > NUL :end exit /B %ERRORLEVEL% :32bits SET PROG_PATH=%ProgramFiles% GOTO :EOF :64bits SET PROG_PATH=%ProgramFiles(x86)% GOTO :EOF REM End of local variables ENDLOCAL REM Local Variables: REM mode: cmd REM comment-start: "REM " REM comment-end: "" REM End: