最近有一个项目是c/s模式的,必须制作安装包,已达到客户使用的简单化。对于我一个以前没有做个安装包的人,在网上找了一些资料,加上自己的一点实践,终于做好了。
好在一开始就有了一个概念,制作安装包可以使用InstallShield,以前觉得这玩意神乎其神的,其实也没什么了,多查资料,多实践就好了。再一次验证了我的一个观点:对于我们开发者而言,知道某种技术或者说工具的用途和概念,比我们知道怎么用他更有益。因为技术和工具太多,我们不可能一次性全部把他们全部学会,也没必要,只有当我们需要做一些事情的时候,我们知道某种东西可以更加方便的实现我们的需求的时候,我们再去学他,这样就事半功倍了。
呵呵,扯了大半天。开始讲述一下大概过程和涉及到的关键东西吧
1、当然是下载一个InstallShield安装一下咯,我的是InstallShield 2010 Premier Edition with version 16
2、新建一个项目吧,这里我们新建一个Windows Installer下的InstallScript MSI Project,至于每个项目的区别就网上查资料看看了。输入项目名称,选择存储路经,确定ok
3、 工具栏下面有三个选项卡,分别是Start Page、Project Assistant和Installation Designer。其中Project Assistant是一个向导式的安装包制作流程,可以完成基本的打包等工作。Installation Designer则是更加具体,功能更加强大的安装包制作方式,可以采用脚本的方式控制安装步骤的执行。我们可以采用Project Assistant和Installation Designer相结合的方式来完成这次制作过程
4、在Project Assistant页面中的下方选择“Application Information”,输入一些软件的基本信息;选择“Installation Requirements”设置一些安装的环境需求,这里没设置;选择“Installation Architecture”设置一下文件的结构,这里我们新建了三个文件夹,分别是Server、Client、Doc,分别存放服务器、客户端和文档内容。这里设置的对应Installation Designer下的Organization下面的features,把Features下面的三个子项更改为Server、Client和Doc;回到“Project Assistant”页面,选择“Application Files”,可以设置每个文件夹下面所包含的内容,这里我们不采用这种静态的方式,因为如果这里设置了,不管你选择只安装服务端或者客户端等,都会把所有文件都拷贝到安装目录下,所以我们采用脚本的方式动态加载需要的文件;当然采用Project Assistant也可以设置注册表等操作,但是后面的操作,我们基本上都采用脚本控制
5、选择Installation Designer页面左边树状栏里选择Behavior And Logic下面的InstallScript,新建一个Script File,系统自动命名为Setup.Rul,这个名字不要更改。在代码编辑区的上面我们可以看到有一个函数生成帮助,可以自动为项目生成一些安装脚本。可以自己试试。下面我把整段代码贴上来,然后对重要的地方进行解释
//=========================================================================== // // 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" // 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); */ //--------------------------------------------------------------------------- // OnBegin // // The OnBegin event is called directly by the framework after the setup // initializes. //--------------------------------------------------------------------------- STRING psvSQLsvr, psvSQLusr, psvSQLpwd; BOOL bvWindowsLogin; prototype number CreateDataBase(STRING,STRING,STRING); prototype number SQLLogin(); //定义登录函数 function number CreateDataBase(svSQLsvr,svSQLusr,svSQLpwd) STRING szCmdLine,szWaitTxt; begin szWaitTxt=" 正在创建所需数据库."; SdShowMsg (szWaitTxt, TRUE); Delay(2); if(bvWindowsLogin) then szCmdLine = "/E /S "+psvSQLsvr+" /Q /"EXEC sp_attach_db @dbname = N'EstartManage',@filename1 = N'"+TARGETDIR^"db//EstartManage_Data.MDF',@filename2 = N'"+TARGETDIR^"db//EstartManage_Log.LDF'/""; else szCmdLine = "/U "+psvSQLusr+" /P "+psvSQLpwd+" /S "+psvSQLsvr+" /Q /"EXEC sp_attach_db @dbname = N'EstartManage',@filename1 = N'"+TARGETDIR^"db//EstartManage_Data.MDF',@filename2 = N'"+TARGETDIR^"db//EstartManage_Log.LDF'/""; endif; if (LaunchAppAndWait("osql.exe", szCmdLine,WAIT) < 0) then MessageBox ("数据库创建失败!请确您的系统中已安装 Microsoft SQL Server 2000. 如仍无法解决,请联系系统供应商!",SEVERE); endif; SdShowMsg (szWaitTxt, FALSE); szWaitTxt=" 正在优化系统数据库."; SdShowMsg (szWaitTxt, TRUE); Delay(2); szCmdLine = "/U "+psvSQLusr+" /P "+psvSQLpwd+" /S "+psvSQLsvr+" /Q /"use EstartManage ; exec sp_updatestats/""; if (LaunchAppAndWait("osql.exe", szCmdLine,WAIT) < 0) then MessageBox ("数据库优化失败!您可以在 sql查询分析器中执行 use EstartManage ; exec sp_updatestats 完成!",SEVERE); endif; SdShowMsg (szWaitTxt, FALSE); return 0; end; function number SQLLogin() number nResult, nSize; STRING sMessage, sTemp; begin Dlg_Sql: SQLRTInitialize2 (); nResult = SQLServerSelectLogin(psvSQLsvr, psvSQLusr, psvSQLpwd, bvWindowsLogin ); if (nResult = BACK) then return BACK; endif; nSize=MAX_PATH; MsiGetProperty(ISMSI_HANDLE, "IS_SQLSERVER_STATUS", sTemp, nSize ); if(sTemp!="0") then nSize = _MAX_PATH; MsiGetProperty(ISMSI_HANDLE, "IS_SQLSERVER_STATUS_ERROR", sMessage, nSize ); if( nSize = 0 ) then sMessage = SdLoadString( IDS_IFX_SQL_ERROR_LOGIN_FAILED ); endif; //MessageBox( sMessage, MB_OK ); //goto Dlg_Sql; endif; return 0; end; 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. Disable (BACKBUTTON); if(!MAINTENANCE)then SdLicense2 ("License", "", "", SUPPORTDIR ^ "license.txt", FALSE); endif; //安装.net framework RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE); if (RegDBKeyExist ("SOFTWARE//Microsoft//.NETFramework") < 0) then if(LaunchAppAndWait (SRCDIR^"dotnetfx20.exe","", LAAW_OPTION_WAIT)<0)then MessageBox ("You haven't installed dotnet framework yet! ", INFORMATION); abort; endif; 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; LIST list, listStartCopy; STRING szFeatureName1; STRING szFeatureName2; STRING szFeatureName3; NUMBER bvOpt1,bvOpt2; //STRING szSrcFile1; //STRING szTarFolder1; begin // 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 // -removeonly is specified and the product is not installed. szFeatureName1 ="Server"; szFeatureName2 ="Client"; szFeatureName3 ="Doc"; 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_SetupType; Dlg_SdFeatureTree: szTitle = ""; szMsg = ""; if (nSetupType = CUSTOM) then nResult = SdFeatureTree(szTitle, szMsg, INSTALLDIR, "", 2); if (nResult = BACK) goto Dlg_SdAskDestPath; endif; Dlg_SQL: //if (nResult = BACK) goto Dlg_Custom; //nResult = OnSQLLogin( nResult ); //if( nResult = BACK ) then //if (!bCustom) then //goto Dlg_SetupType; //else //goto Dlg_SdFeatureTree; //endif; //endif; if (FeatureIsItemSelected(MEDIA, "Server")=1) then if (RegDBKeyExist ("SOFTWARE//Microsoft//Microsoft SQL Server") < 0) then MessageBox("检测到您的电脑未安装Sql Server 2000数据库/n如果已安装或者安装了更高级的版本,请安装数据库时取消安装",INFORMATION); if(LaunchAppAndWait(SRCDIR^"sqlserver2000//autorun.exe","", LAAW_OPTION_WAIT)<0)then MessageBox("安装Sql Server 2000数据库失败,可以在运行程序前先安装数据库",INFORMATION); abort; return -1; endif; //MessageBox("安装Sql Server 2000数据库成功",INFORMATION); endif; nResult = SQLLogin(); if( nResult = BACK ) then if (!bCustom) then goto Dlg_SetupType; else goto Dlg_SdFeatureTree; endif; endif; endif; Dlg_SdStartCopy: szTitle = ""; szMsg = ""; //需要拷贝的源文件 //szSrcFile1 = SRCDIR^"db//*.*"; //拷贝的目的地,目标文件夹 //szTarFolder1 = TARGETDIR^"db//*.*"; //if(CopyFile(szSrcFile1, szTarFolder1)=0) then //MessageBox("复制数据库成功",INFORMATION); //endif; listStartCopy = ListCreate( STRINGLIST ); ListAddString(listStartCopy,"Customer Information:",AFTER); ListAddString(listStartCopy,"User Name: " + svName,AFTER); ListAddString(listStartCopy,"Company Name: " + svCompany,AFTER); ListAddString(listStartCopy,"Destination Location: " + INSTALLDIR,AFTER); switch (nSetupType) case TYPICAL : ListAddString(listStartCopy,"Setup Type: Typical",AFTER); case COMPACT: ListAddString(listStartCopy,"Setup Type: Compact",AFTER); case CUSTOM: ListAddString(listStartCopy,"Setup Type: Custom",AFTER); endswitch; ListAddString(listStartCopy," ",AFTER); ListAddString(listStartCopy,"The Selected Feature:",AFTER); if (FeatureIsItemSelected(MEDIA, szFeatureName1)=1) then ListAddString(listStartCopy," "+szFeatureName1,AFTER); endif; if (FeatureIsItemSelected(MEDIA, szFeatureName2)=1) then ListAddString(listStartCopy," "+szFeatureName2,AFTER); endif; if (FeatureIsItemSelected(MEDIA, szFeatureName3)=1) then ListAddString(listStartCopy," "+szFeatureName3,AFTER); endif; nResult = SdStartCopy( szTitle, szMsg,listStartCopy); ListDestroy(listStartCopy); if (nResult = BACK) then if (FeatureIsItemSelected(MEDIA, "Server")=1) then goto Dlg_SQL; else goto Dlg_SdFeatureTree; endif; 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; //--------------------------------------------------------------------------- // 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; STRING szOption1,szOption2; STRING szFeatureName1; STRING szFeatureName2; STRING szFeatureName3; STRING szSrcFile1; STRING szSrcFile2; STRING szSrcFile3; STRING szSrcFile4; STRING szSrcFile5; STRING szTarFolder1; STRING szTarFolder2; STRING szTarFolder3; NUMBER nResult; STRING szDocFile, szDocFileName;// szDocFile,查找函数返回的查询得到文件名;szDocFileName,要查找的文件名 STRING szfilename,szFolder ,szmsg1,szmsg2; STRING szKey; begin szFeatureName1 ="Server"; szFeatureName2 ="Client"; szFeatureName3 ="Doc"; //需要拷贝的源文件 szSrcFile1 = SRCDIR^"db//*.*"; szSrcFile2 = SRCDIR^"doc//*.*"; szSrcFile3 = SRCDIR^"lib//Client//*.*"; szSrcFile4 = SRCDIR^"lib//Server//*.*"; szSrcFile5 = SRCDIR^"icon//*.*"; //拷贝的目的地,目标文件夹 szTarFolder1 = TARGETDIR^"db//*.*"; szTarFolder2 = TARGETDIR^"doc//*.*"; szTarFolder3 = TARGETDIR^"doc"; //MessageBox(szSrcFile1,INFORMATION); //MessageBox(szSrcFile2,INFORMATION); //MessageBox(szTarFolder1,INFORMATION); //MessageBox(szTarFolder2,INFORMATION); //MessageBox(szTarFolder3,INFORMATION); CopyFile(szSrcFile5, TARGETDIR^"icon//*.*"); if (FeatureIsItemSelected(MEDIA, szFeatureName1)=1) then //安装sql server RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE); szKey = "SOFTWARE//EstartManage"; RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE); if(RegDBSetKeyValueEx(szKey, "VALUE1", REGDB_STRING, "wHpb9E6JNaQ=", -1)<0) then MessageBox("failed",INFORMATION); endif; RegDBSetKeyValueEx(szKey, "VALUE2", REGDB_STRING, "23C2o8FWyF0=", -1); RegDBSetKeyValueEx(szKey, "VALUE3", REGDB_STRING, "", -1); if(CopyFile(szSrcFile4, TARGETDIR^"Server//*.*")=0) then //那么把要拷贝的文件拷贝过去 nResult = FindAllFiles(TARGETDIR^"Server", "*.exe", szDocFile, RESET); //对拷贝过去的文件进行查找,该函数会在第一个符合条件//的文件处停止 while (nResult = 0) LongPathToQuote(szDocFile, TRUE ); //MessageBox(szDocFile,INFORMATION); ParsePath (szDocFileName, szDocFile, FILENAME_ONLY);//对查找到的文件获取文件名 AddFolderIcon(FOLDER_PROGRAMS^"EstartManage//Server",szDocFileName, szDocFile, "", TARGETDIR^"icon//server.ico" , 0 ,"" , REPLACE ); //为该文件创建快捷方式,快捷方式的显示名就是刚才获取的文件名 nResult = FindAllFiles(TARGETDIR^"Server", "*.exe", szDocFile, CONTINUE);//从上一个查找的位置继续向下查找,进行循环 endwhile; if(CopyFile(szSrcFile1, szTarFolder1)=0) then //MessageBox("复制数据库成功",INFORMATION); endif; endif; endif; if (FeatureIsItemSelected(MEDIA, szFeatureName2)=1) then szKey = "SOFTWARE//EstartManage"; RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE); if(RegDBSetKeyValueEx(szKey, "VALUE1", REGDB_STRING, "wHpb9E6JNaQ=", -1)<0) then MessageBox("failed",INFORMATION); endif; RegDBSetKeyValueEx(szKey, "VALUE2", REGDB_STRING, "23C2o8FWyF0=", -1); RegDBSetKeyValueEx(szKey, "VALUE3", REGDB_STRING, "", -1); if(CopyFile(szSrcFile3, TARGETDIR^"Client//*.*")=0) then //那么把要拷贝的文件拷贝过去 //MessageBox("复制文档成功",INFORMATION); nResult = FindAllFiles(TARGETDIR^"Client", "*.exe", szDocFile, RESET); //对拷贝过去的文件进行查找,该函数会在第一个符合条件//的文件处停止 while (nResult = 0) LongPathToQuote(szDocFile, TRUE ); //MessageBox(szDocFile,INFORMATION); ParsePath (szDocFileName, szDocFile, FILENAME_ONLY);//对查找到的文件获取文件名 AddFolderIcon(FOLDER_PROGRAMS^"EstartManage//Client",szDocFileName, szDocFile, "", TARGETDIR^"icon//client.ico" , 0 ,"" , REPLACE ); //为该文件创建快捷方式,快捷方式的显示名就是刚才获取的文件名 nResult = FindAllFiles(TARGETDIR^"Client", "*.exe", szDocFile, CONTINUE);//从上一个查找的位置继续向下查找,进行循环 endwhile; endif; endif; if (FeatureIsItemSelected(MEDIA, szFeatureName3)=1) then if(CopyFile(szSrcFile2, szTarFolder2)=0) then //那么把要拷贝的文件拷贝过去 //MessageBox("复制文档成功",INFORMATION); nResult = FindAllFiles(TARGETDIR^"doc", "*.pdf", szDocFile, RESET); //对拷贝过去的文件进行查找,该函数会在第一个符合条件//的文件处停止 while (nResult = 0) LongPathToQuote(szDocFile, TRUE ); //MessageBox(szDocFile,INFORMATION); ParsePath (szDocFileName, szDocFile, FILENAME_ONLY);//对查找到的文件获取文件名 AddFolderIcon(FOLDER_PROGRAMS^"EstartManage//doc",szDocFileName, szDocFile, "", TARGETDIR^"icon//help.ico" , 0 ,"" , REPLACE ); //为该文件创建快捷方式,快捷方式的显示名就是刚才获取的文件名 nResult = FindAllFiles(TARGETDIR^"doc", "*.pdf", szDocFile, CONTINUE);//从上一个查找的位置继续向下查找,进行循环 endwhile; endif; endif; CopyFile(SRCDIR^"README.TXT", TARGETDIR^"README.TXT"); if (FeatureIsItemSelected(MEDIA, szFeatureName1)=1) then if !MAINTENANCE then CreateDataBase(psvSQLsvr,psvSQLusr,psvSQLpwd); // 创建和 优化数据库 endif; endif; Disable(STATUSEX); ShowObjWizardPages(NEXT); bOpt1 = TRUE; bOpt2 = TRUE; szMsg1 = SdLoadString(IFX_SDFINISH_MSG1); szTitle=""; szMsg1=""; szMsg2=""; szOption1="Show Readme"; szOption2="Create Shortcut on Desktop?"; SdFinishEx(szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2); if (bOpt1=TRUE) then if(FindFile(TARGETDIR, "README.TXT", szDocFile)=0) then LaunchApp ( WINDIR^"Notepad.exe" , TARGETDIR^"README.TXT" ); endif; endif; if(bOpt2=TRUE) then if(bOpt2=TRUE) then if (FeatureIsItemSelected(MEDIA, szFeatureName1)=1) then szDocFile = TARGETDIR^"Server//EstartManage.exe"; endif; if (FeatureIsItemSelected(MEDIA, szFeatureName2)=1) then szDocFile = TARGETDIR^"Client//EstartManage.exe"; endif; LongPathToQuote(szDocFile, TRUE ); if (FeatureIsItemSelected(MEDIA, szFeatureName1)=1) then AddFolderIcon(FOLDER_DESKTOP, "EstartManage" , szDocFile, TARGETDIR^"Server" , TARGETDIR^"icon//server.ico" , 0 ,"" , REPLACE ); endif; if (FeatureIsItemSelected(MEDIA, szFeatureName2)=1) then AddFolderIcon(FOLDER_DESKTOP, "EstartManage" , szDocFile, TARGETDIR^"Client" , TARGETDIR^"icon//client.ico" , 0 ,"" , REPLACE ); endif; endif; endif; //创建删除快捷方式 szfilename = UNINSTALL_STRING +" /UNINSTALL"; nResult = StrFind(szfilename,".exe"); if nResult >=0 then StrSub(szmsg1,szfilename,0,nResult + 4); StrSub(szmsg2,szfilename,nResult + 4,200); LongPathToQuote(szmsg1, FALSE ); LongPathToQuote(szmsg2, FALSE ); szfilename = "/"" + szmsg1 + "/"" +szmsg2; AddFolderIcon(FOLDER_PROGRAMS^"EstartManage","Uninstall",szfilename,WINDIR,TARGETDIR^"icon//client.ico",0,"",REPLACE); endif; end; //--------------------------------------------------------------------------- // OnEnd // // The OnEnd event is called at the end of the setup. This event is not // called if the setup is aborted. //--------------------------------------------------------------------------- function OnEnd() STRING szFeatureName; STRING serviceTarget; STRING szDocFile; begin /* //这个服务所需的文件只有在钩选了某feature时候才会被拷贝, //并且也只有在用户钩选安装了此feature时候才会在安装结束时安装此服务,因此首要判断是否选择了此feature,然后寻找到该执行文件,并且进行安装 */ //szFeatureName="Tool"; //serviceTarget=TARGETDIR^"Tool//Lib//DBAdmin.exe"; //if (FeatureIsItemSelected(MEDIA, szFeatureName)=1) then //if(FindFile(TARGETDIR^"Tool//Lib", "DBAdmin.exe", szDocFile)=0) then //if (LaunchApp (serviceTarget, "") < 0) then //MessageBox ("Unable to launch "+serviceTarget+".", SEVERE); //endif; //endif; //endif; end;
解释部分:
a、首先定义了一些局部变量
STRING psvSQLsvr, psvSQLusr, psvSQLpwd;
BOOL bvWindowsLogin;
因为本安装程序需要sql server数据库的支持,所以以上全局变量用来保存连接数据库信息
b、申明自定义函数
prototype number CreateDataBase(STRING,STRING,STRING); //创建数据库
prototype number SQLLogin(); //定义登录函数
c、函数OnBegin中
if(!MAINTENANCE)then
SdLicense2 ("License", "", "", SUPPORTDIR ^ "license.txt", FALSE);
endif;
用来显示软件的协议,其中license.txt添加到SupportFile中,操作Behavior And Logic->Support Files/BillBoards,在SupportFiles下的第一个Language Independent右边插入license.txt
利用注册表检测软件依赖的环境是否安装
RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE); //设置注册表根
if (RegDBKeyExist ("SOFTWARE//Microsoft//.NETFramework") < 0) then //判断注册表项是否存在
if(LaunchAppAndWait (SRCDIR^"dotnetfx20.exe","", LAAW_OPTION_WAIT)<0)then //运行程序
MessageBox ("You haven't installed dotnet framework yet! ", INFORMATION);
abort;
endif;
endif;
d、函数OnFirstUIBefore中
if (FeatureIsItemSelected(MEDIA, "Server")=1) then
判断是否选择安装服务器,这里跟前面设置的feature相关,其中“Server”就是feature的名字
nResult = SQLLogin();
调用自定义函数SQLLogin
listStartCopy = ListCreate( STRINGLIST );
创建列表
ListAddString(listStartCopy,"Customer Information:",AFTER);
往列表中添加信息
nResult = SdStartCopy( szTitle, szMsg,listStartCopy);
根据开始拷贝需要的文件
ListDestroy(listStartCopy);
销毁列表
e、在函数OnFirstUIAfter中
我们这里的文件拷贝都放在此函数中,根据选择安装的feature动态的拷贝所需文件
CopyFile(szSrcFile5, TARGETDIR^"icon//*.*"); //拷贝目录下的文件
RegDBSetKeyValueEx(szKey, "VALUE1", REGDB_STRING, "wHpb9E6JNaQ=", -1); //写注册表
FindAllFiles(TARGETDIR^"Server", "*.exe", szDocFile, RESET); //查找目录下的文件
AddFolderIcon(FOLDER_PROGRAMS^"EstartManage//Server",szDocFileName, szDocFile, "", TARGETDIR^"icon//server.ico" , 0 ,"" , REPLACE ); //添加快捷方式
CreateDataBase(psvSQLsvr,psvSQLusr,psvSQLpwd); // 调用自定义函数,创建和 优化数据库
SdFinishEx(szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2); //显示复选框
LaunchApp ( WINDIR^"Notepad.exe" , TARGETDIR^"README.TXT" ); //显示readme文件
然后就是创建卸载快捷方式
脚本中还涉及到多种目录的表示方式,具体理解请参考代码
6、发布
a、可以在User Interface下的Dialogs下的Skins设置安装界面的样式
b、选择工具栏中的光标图标制作光盘
7、尾声
好了,制作安装包的过程就差不多这些。文中基本涉及到制作安装的所有基本知识了,如果需要深入,请网上找资料吧。感谢很多网友提供的学习资料。希望对你有所帮助,如有任何疑问或者错误欢迎交流