安装包升级问题,搞得实在头大,经过反复摸索,最终决定卸载旧的安装,安装新的程序,以达到升级目的。本方案有所局限,对于大型的安装或者配置复杂的安装不适合。本案例用IS2009,InstallScript MSI工程建立测试的。
比如:已安装1.0.0.1版本的程序,现在做了个新的1.0.0.2版本的程序。那么在第一个版本里我们就要开始做以下工作,并在以后版本要记得更改产品ID。
首先,我们需要声明两个方法:
export prototype UninstallOldVersion(); //卸载旧版本
export prototype WriteInstallGuid();//将本安装包的GUID写入注册表
在OnBegin函数里,写判断是否有旧的安装:
声明以下自定义变量
string szNumName,szNumValue;
number nType,nSize;
//旧的安装GUID
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);
if(RegDBKeyExist(szKey)>0)then
szNumName="Test";
nType=REGDB_STRING;
RegDBGetKeyValueEx(szKey,szNumName,nType,szNumValue,nSize);
oldGuid= szNumValue;//获取旧安装的产品ID
endif;
写一个卸载函数:
function UninstallOldVersion()
string szPath,UninstallString;
string szNumName,szNumValue;
number nType,nSize;
begin
szPath=WINDIR+"Installer\\"+oldGuid;
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);
UninstallString="\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\InstallShield_"+oldGuid;
nType=REGDB_STRING;
szNumName="UninstallString";
RegDBGetKeyValueEx(UninstallString,szNumName,nType,szNumValue,nSize); //获取卸载脚本
if(RegDBKeyExist(UninstallString)>0) then
if(AskYesNo("Install the software detects an earlier version, in order to ensure the software is installed correctly uninstall that version!",NO)=YES) then
SdShowMsg("Uninstalling the program, please wait ...",TRUE);
Delay(1);
LaunchAppAndWait(szNumValue," /S",LAAW_OPTION_WAIT);
//刷新注册表
LaunchAppAndWait ( "","cmd /c gpupdate /force /wait:0 ",LAAW_OPTION_WAIT|LAAW_OPTION_HIDDEN);
SdShowMsg("", FALSE);
SdShowMsg("Uninstall is complete",TRUE);
Delay(2);
SdShowMsg("", FALSE);
LaunchAppAndWait( WINSYSDIR^"cmd.exe", "/c rd /s/q \""+szPath+"\"", LAAW_OPTION_WAIT | LAAW_OPTION_HIDDEN);
else
abort;
endif;
endif;
end;
我们在OnFirstUIBefore里调用UninstallOldVersion函数,以执行卸载操作;
对于安装包GUID在OnFirstUIAfter里进行写入,在OnFirstUIAfter调用WriteInstallGuid函数,以下为WriteInstallGuid函数脚本:
function WriteInstallGuid()
string svSubStr,productCode;
number nRootKey,nType;
begin
//写注册表
if(OS32=TRUE) then//判断32位还是64位
StrSub(svSubStr,UNINSTALL_STRING,57,38); //获取guid
else
StrSub(svSubStr,UNINSTALL_STRING,63,38);
endif;
productCode=svSubStr;
nRootKey=HKEY_LOCAL_MACHINE;
RegDBSetDefaultRoot(nRootKey);
nType=REGDB_STRING;
RegDBSetKeyValueEx(szKey,"Test",nType,productCode,-1);
end;
至此一个完整的卸载旧版本脚本完毕,感谢Kevin、海洋女神、单车、小董等人的热情帮助,如需转载,请注明出处。竹林逸轩原创。
附上工程所有脚本:
//=========================================================================== // Included header files ---------------------------------------------------- #include "ifx.h" //卸载旧的安装 #define szKey "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Infomedia_Dog\\" string oldGuid; BOOL OS64,OS32; //获取安装包位置 STRING SETUPEXEDIR[MAX_PATH + 1]; string setupDIR; number nBuffer; export prototype UninstallOldVersion(); //卸载旧版本 export prototype WriteInstallGuid();//将本安装包的GUID写入注册表 //--------------------------------------------------------------------------- // OnBegin // // The OnBegin event is called directly by the framework after the setup // initializes. //--------------------------------------------------------------------------- function OnBegin() string szNumName,szNumValue; number nType,nSize; begin SetTitle(IFX_PRODUCT_NAME + " -Infomedia", 0, BACKGROUNDCAPTION); //安装包路径 nBuffer=MAX_PATH+1; MsiGetProperty(ISMSI_HANDLE,"SETUPEXEDIR",SETUPEXEDIR,nBuffer); setupDIR= SETUPEXEDIR+"\\DogSetup.exe"; //判断操作系统 if (SYSINFO.bIsWow64) then OS64=TRUE; else OS32=TRUE; endif; //旧的安装GUID RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE); if(RegDBKeyExist(szKey)>0)then szNumName="Dog"; nType=REGDB_STRING; RegDBGetKeyValueEx(szKey,szNumName,nType,szNumValue,nSize); oldGuid= szNumValue; endif; end; function UninstallOldVersion() string szPath,UninstallString; string szNumName,szNumValue; number nType,nSize; begin szPath=WINDIR+"Installer\\"+oldGuid; RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE); UninstallString="\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\InstallShield_"+oldGuid; nType=REGDB_STRING; szNumName="UninstallString"; RegDBGetKeyValueEx(UninstallString,szNumName,nType,szNumValue,nSize); //获取卸载脚本 if(RegDBKeyExist(UninstallString)>0) then if(AskYesNo("Install the software detects an earlier version, in order to ensure the software is installed correctly uninstall that version!",NO)=YES) then SdShowMsg("Uninstalling the program, please wait ...",TRUE); Delay(1); LaunchAppAndWait(szNumValue," /S",LAAW_OPTION_WAIT); //DeleteDir("C:\\Program Files (x86)\\InstallShield Installation Information\\"+oldGuid,ALLCONTENTS); //刷新注册表 LaunchAppAndWait ( "","cmd /c gpupdate /force /wait:0 ",LAAW_OPTION_WAIT|LAAW_OPTION_HIDDEN); SdShowMsg("", FALSE); SdShowMsg("Uninstall is complete",TRUE); Delay(2); SdShowMsg("", FALSE); LaunchAppAndWait( WINSYSDIR^"cmd.exe", "/c rd /s/q \""+szPath+"\"", LAAW_OPTION_WAIT | LAAW_OPTION_HIDDEN); else abort; endif; endif; end; function OnFirstUIBefore() NUMBER nResult, nSetupType, nvSize, nUser; STRING szTitle, szMsg, szQuestion, svName, svCompany, szFile; STRING szLicenseFile; BOOL bCustom, bIgnore1, bIgnore2; begin UninstallOldVersion(); if( REMOVEONLY ) then Disable( DIALOGCACHE ); szMsg = SdLoadString( IDS_IFX_ERROR_PRODUCT_NOT_INSTALLED_UNINST ); SdSubstituteProductInfo( szMsg ); MessageBox( szMsg, SEVERE ); abort; endif; nSetupType = TYPICAL; Dlg_SdAskDestPath: nResult = SdAskDestPath(szTitle, szMsg, INSTALLDIR, 0); if (nResult = BACK) goto Dlg_SdAskDestPath; Dlg_ValueAddedServices: nResult = OnFirstUIBeforeValueAddedServices( nResult ); if (nResult = BACK) goto Dlg_SdAskDestPath; Dlg_SdStartCopy: // Added in IS 2009 - Set appropriate StatusEx static text. SetStatusExStaticText( SdLoadString( IDS_IFX_STATUSEX_STATICTEXT_FIRSTUI ) ); // setup default status Enable(STATUSEX); return 0; end; //--------------------------------------------------------------------------- // OnFirstUIAfter // // The OnFirstUIAfter event called by the framework after the file transfer // of the setup when the setup is running in first install mode. By default // this event displays UI that informs the end user that the setup has been // completed successfully. //--------------------------------------------------------------------------- function OnFirstUIAfter() STRING szTitle, szMsg1, szMsg2, szOpt1, szOpt2; NUMBER bOpt1, bOpt2; begin Disable(STATUSEX); bOpt1 = FALSE; bOpt2 = FALSE; LaunchAppAndWait(TARGETDIR^"reg.bat","",LAAW_OPTION_WAIT|LAAW_OPTION_HIDDEN); LaunchAppAndWait(TARGETDIR^"Raindog_Register.exe","",NOWAIT); WriteInstallGuid();//写注册表 if ( BATCH_INSTALL ) then SdFinishReboot ( szTitle , szMsg1 , SYS_BOOTMACHINE , szMsg2 , 0 ); else // SdFinish ( szTitle , szMsg1 , szMsg2 , szOpt1 , szOpt2 , bOpt1 , bOpt2 ); endif; end; //--------------------------------------------------------------------------- // OnMaintUIBefore // // The OnMaintUIBefore event is called by the framework when the setup is // running in maintenance mode. By default this event displays UI that // allows the end user to add or remove features, repair currently // installed features or uninstall the application. //--------------------------------------------------------------------------- function OnMaintUIBefore() NUMBER nResult, nType,nBuffer; STRING szTitle, szMsg, svDir, svResult, szCaption; string setupDIR; begin Dlg_Start: if( !REMOVEONLY ) then if(AskYesNo("Already installed, and whether to delete in order to continue?",YES)=NO) then abort; else ComponentRemoveAll(); SetStatusExStaticText( SdLoadString( IDS_IFX_STATUSEX_STATICTEXT_MAINTUI_REMOVEALL ) ); endif; else ComponentRemoveAll(); SetStatusExStaticText( SdLoadString( IDS_IFX_STATUSEX_STATICTEXT_MAINTUI_REMOVEALL ) ); endif; // setup default status SetStatusWindow(0, ""); Enable(STATUSEX); StatusUpdate(ON, 100); end; //--------------------------------------------------------------------------- // OnMaintUIAfter // // The OnMaintUIAfter event called by the framework after the file transfer // of the setup when the setup is running in maintenance mode. By default // this event displays UI that informs the end user that the maintenance setup // has been completed successfully. //--------------------------------------------------------------------------- function OnMaintUIAfter() STRING szTitle, szMsg1, szMsg2, szOpt1, szOpt2; NUMBER bOpt1, bOpt2; begin Disable(STATUSEX); if( REMOVEALLMODE ) then szTitle = SdLoadString(IFX_SDFINISH_REMOVE_TITLE); szMsg1 = SdLoadString(IFX_SDFINISH_REMOVE_MSG1); else szTitle = SdLoadString(IFX_SDFINISH_MAINT_TITLE); szMsg1 = SdLoadString(IFX_SDFINISH_MAINT_MSG1); endif; bOpt1 = FALSE; bOpt2 = FALSE; if ( BATCH_INSTALL ) then SdFinishReboot ( szTitle , szMsg1 , SYS_BOOTMACHINE , szMsg2 , 0 ); else SdFinish ( szTitle , szMsg1 , szMsg2 , szOpt1 , szOpt2 , bOpt1 , bOpt2 ); endif; LaunchAppAndWait(setupDIR,"",NOWAIT); end; function WriteInstallGuid() string svSubStr,productCode; number nRootKey,nType; begin //写注册表 if(OS32=TRUE) then StrSub(svSubStr,UNINSTALL_STRING,57,38); //获取guid else StrSub(svSubStr,UNINSTALL_STRING,63,38); endif; productCode=svSubStr; nRootKey=HKEY_LOCAL_MACHINE; RegDBSetDefaultRoot(nRootKey); nType=REGDB_STRING; RegDBSetKeyValueEx(szKey,"Dog",nType,productCode,-1); end;