前一篇介绍了如何使用InstallShield打包自动部署JavaWeb的运行环境,如果有不了解的,请参考:
使用InstallShield打包Tomcat+MySql+Jdk的Web运行环境详解
本文主要介绍如何使用InstallShield打包自动部署应用。具体应用是多种多样的,但是打包的思路基本一样的。拷贝文件,系统注册等操作,InstallShield都会替你做了,我们只需要在InstallScript里对应的部首阶段中,调用自己的安装和卸载批处理即可。
为了打包简单,我设计了一个批处理,在InstallShield的脚本里调用即可。具体批处理【real_update_DVCSWeb.bat】内容如下:
@ echo off
::switch to work dir
cd /d %~dp0
echo %cd%
echo install tomcat service
call "%cd%"\install_tomcat.bat
echo stop tomcat service
sc stop dvcs_tomcat
echo kill tomcat6
taskkill /f /t /im tomcat6.exe
echo backup mysql data [wait for a few minutes]
"%MYSQL_HOME%"\bin\mysqldump -uroot -p123456 dvcs > "%cd%\dvcs_data_bak_%DATE:~0,4%%DATE:~5,2%%DATE:~8,2%.sql"
echo update war packet
rd /s/q "%CATALINA_HOME%\webapps\dvcs"
rd /s/q "%CATALINA_HOME%\work\Catalina\localhost\dvcs"
copy /y "%cd%\DVCSWeb\dvcs.war" "%CATALINA_HOME%\webapps"
echo update [system.properties]
copy /y "%cd%\DVCSWeb\system.properties" "%DVCS_HOME%\conf"
echo update [mail.properties]
copy /y "%cd%\DVCSWeb\mail.properties" "%DVCS_HOME%\conf"
echo start tomcat service
sc start dvcs_tomcat
批处理中调用的其它批处理,读者可以参考前面的文章,可以找到线索,这里不再细说,批处理里的注释也说得很清楚。
同样,为了生成安装日志,再创建一个批处理【update_DVCSWeb.bat】封装起来,供InstallScript调用,具体内容如下:
@ echo off
::切换到工作目录
cd /d %~dp0
echo %cd%
::调用更新批处理
call real_update_DVCSWeb.bat > update_DVCSWeb.log
我的应用在卸载时,主要停止Tomcat即可,后面删除文件和目录由InstallShield替我做了,具体卸载批处理【unstall_DVCSWeb.bat】内容如下:
@ echo off
::切换到工作目录
cd /d %~dp0
::echo 停止Tomcat
::call %DVCS_HOME%\stop_tomcat.bat
echo 停止Tomcat服务...
sc stop dvcs_tomcat
我创建了同样的InstallShield工程类型【InstallScript MSI Project】,具体脚本内容如下:
//===========================================================================
//
// File Name: Setup.rul
//
// Description: Blank setup main script file
//
// Comments: Blank setup is an empty setup project. If you want to
// create a new project via. step-by step instructions use the
// Project Assistant.
//
//===========================================================================
// Included header files ----------------------------------------------------
#include "ifx.h"
// Microsoft Visual C++ 2012 Redistribute Package
#define VS_2012_REDIST_X64_KEY "SOFTWARE\\Classes\\Installer\\Dependencies\\{ca67548a-5ebe-413a-b50c-4b9ceb6d66c6}"
BOOL bRetainUseData, g_isVs2012X64Installed;
// Note: In order to have your InstallScript function executed as a custom
// action by the Windows Installer, it must be prototyped as an
// entry-point function.
// The keyword export identifies MyFunction() as an entry-point function.
// The argument it accepts must be a handle to the Installer database.
/* export prototype MyFunction(HWND); */
export prototype IsVS2012X64Installed();
// 判断VS2012分发布是否已安装
function IsVS2012X64Installed()
begin
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);
if(RegDBKeyExist(VS_2012_REDIST_X64_KEY) == 1) then
//MessageBox ("VS2012 has installed", INFORMATION);
g_isVs2012X64Installed = TRUE;
else
//MessageBox ("VS2012 not installed", INFORMATION);
g_isVs2012X64Installed = FALSE;
endif;
end;
//---------------------------------------------------------------------------
// OnFirstUIBefore
//
// The OnFirstUIBefore event is called by the framework when the setup is
// running in first install mode. By default this event displays UI allowing
// the end user to specify installation parameters.
//---------------------------------------------------------------------------
function OnFirstUIBefore()
NUMBER nResult, nSetupType, nvSize, nUser;
STRING szTitle, szMsg, szQuestion, svName, svCompany, szFile;
STRING szLicenseFile;
BOOL bCustom, bIgnore1, bIgnore2;
begin
//SetTitle("Installation "+IFX_PRODUCT_NAME,0,BACKGROUNDCAPTION);
// TO DO: if you want to enable background, window title, and caption bar title
// SetTitle( @PRODUCT_NAME, 24, WHITE );
// SetTitle( @PRODUCT_NAME, 0, BACKGROUNDCAPTION );
// Enable( FULLWINDOWMODE );
// Enable( BACKGROUND );
// SetColor(BACKGROUND,RGB (0, 128, 128));
// Added in InstallShield 15 - Show an appropriate error message if
// -uninst is specified and the product is not installed.
if( REMOVEONLY ) then
Disable( DIALOGCACHE );
szMsg = SdLoadString( IDS_IFX_ERROR_PRODUCT_NOT_INSTALLED_UNINST );
SdSubstituteProductInfo( szMsg );
MessageBox( szMsg, SEVERE );
abort;
endif;
nSetupType = TYPICAL;
Dlg_SdWelcome:
szTitle = "";
szMsg = "";
nResult = SdWelcome(szTitle, szMsg);
if (nResult = BACK) goto Dlg_SdWelcome;
szTitle = "";
svName = "";
svCompany = "";
Dlg_SdRegisterUser:
szMsg = "";
szTitle = "";
nResult = SdRegisterUser( szTitle, szMsg, svName, svCompany );
if (nResult = BACK) goto Dlg_SdWelcome;
Dlg_SetupType:
/*
szTitle = "";
szMsg = "";
nResult = SetupType2(szTitle, szMsg, "", nSetupType, 0);
if (nResult = BACK) then
goto Dlg_SdRegisterUser;
else
nSetupType = nResult;
if (nSetupType != CUSTOM) then
nvSize = 0;
FeatureCompareSizeRequired(MEDIA, INSTALLDIR, nvSize);
if (nvSize != 0) then
MessageBox(szSdStr_NotEnoughSpace, WARNING);
goto Dlg_SetupType;
endif;
bCustom = FALSE;
goto Dlg_SQL;
else
bCustom = TRUE;
endif;
endif; */
Dlg_SdAskDestPath:
nResult = SdAskDestPath(szTitle, szMsg, INSTALLDIR, 0);
if (nResult = BACK) goto Dlg_SdRegisterUser;
Dlg_SdFeatureTree:
szTitle = "";
szMsg = "";
if (nSetupType = CUSTOM) then
nResult = SdFeatureTree(szTitle, szMsg, INSTALLDIR, "", 2);
if (nResult = BACK) goto Dlg_SdAskDestPath;
endif;
Dlg_SQL:
nResult = OnSQLLogin( nResult );
if( nResult = BACK ) then
if (!bCustom) then
goto Dlg_SetupType;
else
goto Dlg_SdFeatureTree;
endif;
endif;
Dlg_ValueAddedServices:
nResult = OnFirstUIBeforeValueAddedServices( nResult );
if (nResult = BACK) goto Dlg_SQL;
Dlg_SdStartCopy:
szTitle = "";
szMsg = "";
nResult = SdStartCopy2( szTitle, szMsg );
if (nResult = BACK) then
goto Dlg_ValueAddedServices;
endif;
// Added in IS 2009 - Set appropriate StatusEx static text.
SetStatusExStaticText( SdLoadString( IDS_IFX_STATUSEX_STATICTEXT_FIRSTUI ) );
// setup default status
Enable(STATUSEX);
return 0;
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;
STRING szTitle, szMsg, svDir, svResult, szCaption,szCmd,szDir;
begin
//SetTitle("Installation "+IFX_PRODUCT_NAME,0,BACKGROUNDCAPTION);
//加入终止进程函数
// TO DO: if you want to enable background, window title, and caption bar title
// SetTitle( @PRODUCT_NAME, 24, WHITE );
// SetTitle( @PRODUCT_NAME, 0, BACKGROUNDCAPTION );
// SetColor(BACKGROUND,RGB (0, 128, 128));
// Enable( FULLWINDOWMODE );
// Enable( BACKGROUND );
Dlg_Start:
bRetainUseData=TRUE;
nType = REMOVEALL;
nResult = MessageBox( SdLoadString( IFX_MAINTUI_MSG ), MB_YESNO );
if (nResult != IDYES ) then
abort;
endif;
nResult = MessageBox( "Do you want to reserve the config data?(Y:Reserve, N:Dispose)", MB_YESNOCANCEL );
if (nResult == IDNO ) then
bRetainUseData=FALSE;
endif;
if (nResult == IDCANCEL ) then
abort;
endif;
// 停止Tomcat
szCmd = TARGETDIR ^ "\\DVCS Server\\unstall_DVCSWeb.BAT";
LaunchAppAndWait(szCmd,"",LAAW_OPTION_WAIT|LAAW_OPTION_SHOW_HOURGLASS|LAAW_OPTION_HIDDEN);
// 退出DVCS Server进程
szCmd = TARGETDIR ^ "\\DVCS Server\\1.BAT";
LaunchAppAndWait(szCmd,"",LAAW_OPTION_WAIT|LAAW_OPTION_SHOW_HOURGLASS|LAAW_OPTION_HIDDEN);
switch(nType)
case REMOVEALL:
// 删除DVCS服务
LaunchAppAndWait("sc", "delete dvcs_server", LAAW_OPTION_WAIT);
ComponentRemoveAll();
// Added in IS 2009 - Set appropriate StatusEx static text.
SetStatusExStaticText( SdLoadString( IDS_IFX_STATUSEX_STATICTEXT_MAINTUI_REMOVEALL ) );
case REPAIR:
ComponentReinstall();
// Added in IS 2009 - Set appropriate StatusEx static text.
SetStatusExStaticText( SdLoadString( IDS_IFX_STATUSEX_STATICTEXT_MAINTUI_REPAIR ) );
case MODIFY:
// Added in IS 2009 - Set appropriate StatusEx static text.
SetStatusExStaticText( SdLoadString( IDS_IFX_STATUSEX_STATICTEXT_MAINTUI_MODIFY ) );
endswitch;
// 卸载VS2012分发包
if(g_isVs2012X64Installed) then
szCmd = TARGETDIR ^ "\\DVCS Server\\vcredist_x64.exe";
LaunchAppAndWait(szCmd,"",LAAW_OPTION_WAIT|LAAW_OPTION_SHOW_HOURGLASS|LAAW_OPTION_HIDDEN);
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);
if(!bRetainUseData) then
DeleteProgramFolder(TARGETDIR+"DVCS Server");
DeleteProgramFolder(FOLDER_PROGRAMS+"DVCS Server");
endif;
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;
end;
//---------------------------------------------------------------------------
// OnInstallFilesActionAfter
//
// The InstallFilesActionAfter event is called just after the standard MSI
// action 'InstallFiles' is executed.
//---------------------------------------------------------------------------
function OnInstallFilesActionAfter()
STRING szDir;
STRING szCmd;
NUMBER ret;
begin
if( REMOVEALLMODE ) then
else
// 退出DVCS Server进程
szCmd = TARGETDIR ^ "\\DVCS Server\\1.BAT";
LaunchAppAndWait(szCmd,"",LAAW_OPTION_WAIT|LAAW_OPTION_SHOW_HOURGLASS|LAAW_OPTION_HIDDEN);
// 安装VS2012分发包
if(!g_isVs2012X64Installed) then
szCmd = TARGETDIR ^ "\\DVCS Server\\vcredist_x64.exe";
LaunchAppAndWait(szCmd,"",LAAW_OPTION_WAIT|LAAW_OPTION_SHOW_HOURGLASS|LAAW_OPTION_HIDDEN);
endif;
// 启动DVCS服务
szDir = " create dvcs_server binPath= \""+INSTALLDIR+"DVCS Server\\dvcs_daemon.exe\" type= own start= auto ";
if( LaunchAppAndWait("sc",szDir, LAAW_OPTION_WAIT)>=0) then
LaunchAppAndWait("sc","start dvcs_server", LAAW_OPTION_WAIT);
endif;
// 更新DVCS Web
szCmd = TARGETDIR ^ "\\DVCS Server\\update_DVCSWeb.BAT";
LaunchAppAndWait(szCmd,"",LAAW_OPTION_WAIT|LAAW_OPTION_SHOW_HOURGLASS|LAAW_OPTION_HIDDEN);
endif;
end;
//---------------------------------------------------------------------------
// OnResumeUIBefore
//
// The OnResumeUIBefore event is called when end user runs installation that
// is performing a resumed install. Usually this happens by specifying
// a property like REINSTALL or ADDLOCAL at the command line when the
// product is already installed. After this function returns,
// ComponentTransferData is called to perform file transfer.
//---------------------------------------------------------------------------
function OnResumeUIBefore()
int nResult;
string szTitle, szMsg ,szCmd;
begin
// 由于从V3.7.27后不能覆盖升级(文件不能更新,具体原因不清楚 20181213 pst)
// 需要先卸载旧版本,不支持覆盖安装
MessageBox("The installation has detected the DVCS Server has been installed. " +
"Please uninstall it first.", INFORMATION);
abort;
Dlg_SdWelcome:
szTitle = SdLoadString(ISWI_RESUMEUI_TITLE);
szMsg = SdLoadString(ISWI_RESUMEUI_MSG);
nResult = SdWelcome(szTitle, szMsg);
// Added in IS 2009 - Set appropriate StatusEx static text.
szMsg = SdLoadString( IDS_IFX_STATUSEX_STATICTEXT_UPDATEUI );
SdSubstituteProductInfo( szMsg );
SetStatusExStaticText( szMsg );
Enable(STATUSEX);
// 停止Tomcat
szCmd = TARGETDIR ^ "\\DVCS Server\\unstall_DVCSWeb.BAT";
LaunchAppAndWait(szCmd,"",LAAW_OPTION_WAIT|LAAW_OPTION_SHOW_HOURGLASS|LAAW_OPTION_HIDDEN);
// 退出DVCS Server进程
szCmd = TARGETDIR ^ "\\DVCS Server\\1.BAT";
LaunchAppAndWait(szCmd,"",LAAW_OPTION_WAIT|LAAW_OPTION_SHOW_HOURGLASS|LAAW_OPTION_HIDDEN);
DeleteProgramFolder(TARGETDIR+"DVCS Server\\Web");
DeleteProgramFolder(FOLDER_PROGRAMS+"DVCS Server\\Web");
end;
//---------------------------------------------------------------------------
// OnBegin
//
// The OnBegin event is called directly by the framework after the setup
// initializes.
//---------------------------------------------------------------------------
function OnBegin()
begin
// TO DO: you may change default non-UI setting, for example
//
// You may also perform your custom initialization steps, check requirements, etc.
// 检查VS2012分发包是否已经安装
IsVS2012X64Installed();
end;
通过前面文件和这篇文章的介绍,对如何打包自动部署Web应用的思路和具体办法进行了比较详细的介绍,希望对大家有所帮助。
这些自动化打包部署的方法大概花了两周时间,慢慢摸索出来的。之前的开发工程师写了一个很长的手工安装文档,按照这个文档一步一步安装的话,估计要半天时间。并且我们的客户基本没有计算机经验,让他们如何打开控制台执行命令都不清楚。
其实做软件这个行业,要积极发现问题,并耐心解决,不能怕麻烦。如果工程师怕麻烦,最终就把麻烦丢给了客户,造成客户的丢失。