InstallShield教程

注意：

InstallShield简明使用教程

用InstallShield制作专业Windows安装软件

如何在InstallShield中使用自己的DLL

installshield中实现ODBC注册、序列号、防拷贝等

InstallShield Express使用簡介(二)


用InstallShield制作专业Windows安装软件[1999-06-01]

苏贵洋

--------------------------------------------------------------------------------

    InstallShield可以说是软件安装的最好制作工具。其简单的操作、完全可视化的界面、方便的调试功能、多平台（Windows3.1, Windows95, WindowsNT3.5, Windows NT4.0 ）语言（中文、各种西文）的支持使它几乎成为了安装制作的标准。难怪微软在它的拳头产品Visual C++4.X中开始,就以捆绑的形式包括了InstallShield3。而今，随着日月的推移，InstallShield更是羽翼丰满，又陆续推出了InstallShield Professional 5.X(包括East Edition,West Edition)和InstallShield 6.0，功能更为强大，操作更为简便。对于Shareware软件的制作者，包装上一个漂亮的安装程序，实在是非常必要。本文简要探讨一下用InstallShield制作安装软件的方法，希望对感兴趣的朋友有所帮助。

    在InstallShield的各种最新版本中，其专门制作的East Edition，可应用于汉语(GB、BIG5)、英语、印度尼西亚语、日语、韩语、俄语、土耳其语、泰国语等多语种。本文便以InstallShield East Edition 5.1为探讨对象进行讨论。InstallShield的其它语种版本的操作和East Edition几乎完全相同。

    进入InstallShield East Edition 5.1后便是两个“向导”面对你。

    习惯用VB的朋友可以用VB5 Project Wizard,它需要你的系统中安装了VB5。

    更为常用的是Project Wizard,它可以定制更为普便适用的安装程序。进入Project Wizard后如图1：在第一栏中写入你的程序的名字，第二栏中写入公司的名字，在第三栏中选择开发程序使用的根据，第四栏中选择程序的种类，最后一栏中填入程序的可执行文件的完整路径和名字。单击下一步，进入选择定制对话框：安装自己的喜好选择希望安装过程进行时出现的对话框，按Priview键可以预览一下相应对话框的效果。接下来是选择要安装目标平台。也即程序将被运行在什么平台之上。InstallShield共提供了四种平台供选择（Win31, win95, WinNT3.5, Windows NT4.0 ）。然后是多语种支持,也就是安装时可以提供的语言支持。再向下依次是安装类型选择、指定构成成份、指定文件组，最后是所有选项的概括。完成选择后便可得到你自己定做的Project，进入InstallShield的可视化编程环境。

    下面让我们一步一步地完成我们的制作。

    整个InstallShield的可视化程度很高。支持鼠标右键的操作，在各个位置的鼠标右键可激活各种功能；编译、调试方便，简直是VC＋＋这种大型程序的简写本，却又比VC＋＋方便了许多。

    一、在左面的选项中选择Scripts。

    这是全部制作的核心部分，也是我们所最应集中精力攻克的小小关口。当然不更改Scripts中的源程序也能制作一个标准的安装程序,但如果能够控制Scripts的编程,整个安装程序的制作水准就可以达到一个新的高度,这也许是您与普通制作者区别的开始吧。其实InstallShield的Scripts非常类似于C和C＋＋的程序编写，相信对大多数程序员来说是非常容易掌握的。而对于没有什么C和C＋＋的基础的朋友来讲，看完这篇文章后，相信你也能很好地去制作自己的Scripts，因为它具有相当程度的重复性，更容易被“依葫芦画瓢”。

    Scripts的布局同C语言非常类似。首先是头文件的包含，紧接着是字符串的定义、函数原形的说明、全局变量的说明。你可以做的是在此加上你的函数说明、全局变量的说明。

    Scripts中遵循C的规则，同样有局部变量和定义。遵循C＋＋的注释规则，可以用// 注释内容来进行单行注释，也可以用/* 注释内容 */来注释一块语句。所有的关键字、宏定义都以不同颜色的字体标出，非常直观。Scripts 的编程遵循结构化编程的思想，提供了大量类似Windows API的函数库供调用，每个宏定义都有详细的说明，每个函数除了详细地说明，解释每个变量的意义外，还都附有相应的例子，参考这些说明和例子，可以让新手在非常短的时间内上路。对用VC＋＋开发过Windows程序的朋友来讲，简直就是一种6＝2×3的转变而已，可以非常轻松地掌握。

    在程序的最前段，是program…………………endprogram，它相当于C中的main() {……}主函数。后面是一个个子函数体的程序，排列顺序是按调用顺序排列。全部函数都非常简单易懂，并且一般不需太大改动。下面将几个常用、经常改动的函数加以说明。

    （1） function SetupFolders()

    function SetupFolders()

    NUMBER nResult;

    STRING szFolderDir;

    begin

    szProgramFolder = FOLDER_PROGRAMS^

    SHELL_OBJECT_FOLDER; //建立程序组或快捷方式的位置

szItemName = "眼部图象多功能处理系统"; //应用程序名称

szProgram = TARGETDIR^'eye95.exe'; //可执行文件名

szParam = "";

    LongPathToQuote (szProgram, TRUE);//合并路径

    LongPathToShortPath (szParam);//转为短路径,专为Win31和WinNT3.5而用

    szCommandLine = szProgram + " " + szParam; //生成命令行

    szWorkingDir = TARGETDIR;//工作路径

    szIconPath = "";

    nIcon = 0;

    szShortCutKey = "";

    nFlag = REPLACE;

    AddFolderIcon (szProgramFolder, szItemName,

    szCommandLine,

    szWorkingDir, szIconPath, nIcon,

    szShortCutKey, nFlag);

    szProgramFolder = FOLDER_DESKTOP;

    LongPathToQuote(szCommandLine, TRUE);

if(SprintfBox( OK|CANCEL,"请选择：","%s","你想在桌面上创建快捷方式吗?")==6)

    then

    AddFolderIcon(szProgramFolder,szItemName,szCommand

    Line,

    szWorkingDir,szIconPath,nIcon,szShortCutKey,

    nFlag);

endif;

szProgramFolder = FOLDER_PROGRAMS^ SHELL_OBJECT_FOLDER;

szItemName="readme";

szProgram = WINDIR ^ "notepad.exe";

szParam = TARGETDIR^"readme.txt";

LongPathToQuote (szProgram, TRUE);

LongPathToShortPath (szParam);

szCommandLine = szProgram + " " + szParam;

AddFolderIcon(szProgramFolder,szItemName,

    szCommandLine ,

    szWorkingDir, szIconPath, 0,

    szShortCutKey,nFlag );

    nResult = CreateShellObjects( "" );

    return nResult;

    end;

    其实这段程序说白了是对AddFolderIcon的一个应用而已。应用AddFolderIcon来在开始选单中添加程序组、程序项或在桌面桌面添加快捷方式等等。所以首先读一下AddFolderIcon的说明非常必要。它共有八个入口参数。第一个参数szProgramFolder是确定要在Win95中添加选单的位置（路径），例如

    "C:\\WINDOWS\\STARTMENU\\PROGRAMS\\ACCESSORIES\\GAMES"。

    而在Windows95和WinNT4.0中，还可以用系统的宏定义：FOLDER_DESKTOP(添加在桌面上)、FOLDER_DESKTOP(添加在开始选单中)、FOLDER_PROGRAMS(添加在开始－〉程序选单中)等。第二个参数为szItemName，即添加的图标的名称（应用程序的名称）。第三个参数szCommandLine相对繁琐一些。它为了指定可执行程序和它的命令行，或者在子目录下的全路径（仅适用于Windows95&winNT4.0）。szWorkingDir为工作路径，可为空：“”，或为TARGETDIR（目标路径）。szIconPath为图标路径，一般设为空：“”。nIcon为图标序数，即若应用程序有若干个图标，想显示那个，依次为0，1，2……。

    szShortCutKey用来定义快捷键。nFlag用来指定图标的外观。如果在路径中包含长路径名，则必需用‘’或“”来包含，然后用LongPathToQuote函数来合并。当用于16位的Win31和WinNT3.5时，还应再调用一下LongPathToShortPath进行转换。如此便可创建程序组、程序项或快捷方式了。太麻烦了？没关系，如果您认为这一段操作实在麻烦，您完全可以略过，到Resource中去完成，详情请往后看。

    （2）function SetupScreen()

    begin

    Enable( FULLWINDOWMODE );

    Enable( INDVFILESTATUS );

    SetTitle( "眼科多功能处理系统安装程序", 28,YELLOW );//修改字体和颜色

    SetTitle( "眼科多功能处理系统", 0, BACKGROUNDCAPTION ); // 标题行的字体和颜色

    Enable( BACKGROUND );

    Delay( 1 );

    end;

    这儿主要是SetTitle (szString, nPointSize, nColor)函数的应用。

    三个参数分别代表了所写字符串的内容、字体大小、文字颜色。

    （3）function DialogShowSdWelcome()

    NUMBER nResult;

    STRING szTitle, szMsg;

    begin

    szTitle = "欢迎";

    szMsg = "欢迎您光临 眼科多功能处理系统 安装程序！";

    nResult = SdWelcome( szTitle, szMsg );

    return nResult;

    end;

    在这个函数里写入您想制作程序的标题。

    （4）function SetupRegistry()

    NUMBER nResult;

STRING szKey, szNumName, szNumValue, svNumValue;

    NUMBER nType, nSize;

    begin

    szKey="Robert\\RobertSoftware\\Spirit\\Version";//自己的主键

    szNumName = "TestValue";//键名

    szNumValue = "12345";//键值

    nType = REGDB_NUMBER;//类型

    nSize = -1;//指定大小

    RegDBSetKeyValueEx(szKey, szNumName, nType, szNumValue,nSize) ;//创建

    nResult = CreateRegistrySet( "" );

    return nResult;

    end;

    通过这种方法修改注册表，再辅以一些算法，可以投入很小但起到很好的加密程序的作用，您不妨一试！ ?

    （5）function DialogShowSdFinishReboot()

    NUMBER nResult, nDefOptions;

    STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;

    NUMBER bOpt1, bOpt2;begin

    if (!BATCH_INSTALL) then

     bOpt1 = FALSE;//不选

     bOpt2 = FALSE;//不选

     szMsg1 = "%P 安装结束！\n";//%P代表安装程序名字。

szMsg2 = "按结束键结束 %p 安装。";//提示信息

szOption1 = "我想看自述文件。";

     szOption2 = "我想现在就运行程序。";

     nResult = SdFinish( szTitle, szMsg1, szMsg2,

    szOption1, szOption2, bOpt1, bOpt2 );

if(bOpt1) then

     LaunchAppAndWait(WINDIR^"Notepad.exe",TARGETDIR^"readme.txt",WAIT);//如果选中，调用Windows的笔记本载入自述文件。

    endif; if(bOpt2) then

     LaunchApp(TARGETDIR^'eye95.exe',"");//如选中，立刻执行应用程序

    endif;

     return 0;

    endif;

    nDefOptions = SYS_BOOTMACHINE;

    szTitle = "";

    szMsg1 = "";

    szMsg2 = "";

    nResult = SdFinishReboot( szTitle, szMsg1,

    nDefOptions, szMsg2, 0 );//由此控制决定是否重新启动计算机。

    return nResult;

    end;

    这一段程序便是安装到最后，可以提示用户是否看自述文件、是否立刻启动程序运行、是否重新启动计算机。

    Scripts最需要改动的地方可能就是这五个地方。其它则根据制作者自己的需要来做相应修改。

    二、修改File Groups

    双击相应的Examples Files、Help Files、Program DLLs、Program Executable Files、Shared Dlls，在相应的Links中，单击右键，可以插入一组文件、一个文件夹或一个文件。而在Examples Files、Help Files、Program DLLs、Program Executable Files、Shared Dlls中分别加入文件是为了在程序安装时的选项安装。更为简便的方法是在Tools中启动Launch Explorer，然后把所需的文件或文件夹拖拉到右面空白处即可。

    三、修改Components

    单击Program Files、Example Files、Help Files或Shared Dlls，在右面的表格中双击Include File Groups，在弹出的属性对话框里单击Add…，加入相应的文件组。

    四、修改Setup Types

    单击Compact、Typical或Custom，在右面的表格中选择各自包括的组成成份。

    注：有了二、三、四项的操作，才能完成安装时的“典型安装、简洁安装和定制安装”的选择。

    五、修改Setup Files

    在Splash Screen-〉Language Independent中你会发现一个Setup.bmp文件，这个是系统提供给你的安装开始时的闪烁画面。你可以用你的封面替代这个setup.bmp。在Language Independent-〉Operating System Independent中，你会发现license.txt和infolist.txt。你可以将你的应用程序的说明、版权信息写入相应文件。

    六、修改Resource

    在Register Entires中，你可以添加你的键值。对Register Entires单击鼠标右键，单击New Entry,便可在右面的Register Set中加入自己的键值。

    在Shell Objects中，有Explorer Shell和Program Manager Shell两个分类，分别是为了windows95、WinNT4.0和win31、winNT3.5设计的。在Explorer Shell中，又有Desktop、Start Menu、Programs、Startup的层次之分。你可以在任一层单击右键，插入您所需要加的快捷方式或文件夹。

    单击快捷方式或文件夹，双击右面的表格选项，依次填入空白项，那么在您理想的目的地的文件夹或快捷方式便建好了。不要着急去按下Run Setup工具按钮，否则您会发现您运行后得到的并不完全是您所设计的！这是因为您少了：

    七、运行Media Wizard

    在Media栏，单击Media Build Wizard，按照提示一步一步执行，直至结束（而实际上您仅需连续按“下一步”按钮）。您完全可以再此基础上加上更多的更精彩的小花招，如：加密、安装拷贝时的不同的背景变换、制成一个自解包的安装文件、做一个带时间限制的试用版安装等等，InstallShield都可以满足您的需要。但这些小花招,基本都需要您对Scripts的熟练掌握,这些都是用简洁方式所不能控制的。

    好了，您可以Run Setup了。怎么样？够不够专业？酷不酷？可不要把嘴乐歪了


如何在InstallShield中使用自己的DLL

郑州工业大学
傅常顺

---- 作为一个开发人员，当我们为用户开发好应用系统时，就要包装分发自己的程序给最终用户。一般情况下，相应的开发系统中也提供了相应的分发工具，例如Visual Basic6.0中的 [Package & Deployment 向导] ，但是有的开发系统提供的都是英文版的，为了适应中国用户，我们需要选择一款易学易用，界面友好的工具软件，而 InstallShield 就是最好的工具之一。在此我选用的是 InstallShield 5.1 远东专业版本，此版本可以制作出支持多种语言界面的安装程序。

---- InstallShield 的功能相当强大，能够对系统和安装需要提供丰富的函数支持，有足够灵活的界面控制支持，而且其脚本语言特点与Visual C++的代码极其相似，非常适合使用Visual C++的开发者使用。

---- 但是，在某些情况下，InstallShield不能提供能完成某种特殊功能的相应函数，这时需要我们自己开发出能够完成此功能的函数，然后放在InstallShield中调用，达到与其完美的结合，DLL是最佳的选择。

---- 本文以一个实例介绍了如何生成自己的DLL，以及如何在 InstallShield中调用。

一、制作DLL：

---- 此动态库函数主要是显示出传给自己的字符串，并做了改动返回（如果要在InstallShield中使用改动过的字符串，在InstallShield中原型声明时，用POINTER对应LPSTR），并且根据传入的数据返回不同的返回值，用户只要根据此原理实现自己的函数即可：

---- 1、在Visual C++中的 New 中选择 MFC AppWizard(DLL) 工程类型，输入工程名Setup00,点OK，直接 Finish 即可。然后在ClassView中，用鼠标右击Csetup00App，选择Add Member Function…,在Function Type中输入int，在Function Declaration中输入Test(LPSTR lpszStr, int iVal)，Access类型选择Public，然后输入下面函数体。 Setup00.DLL的Test函数例码:

 int CSetup00App::Test(LPSTR
lpszStr, int iVal) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); AfxMessageBox(lpszStr);
//如果想改变字符串，用下面方法 strcpy(lpszStr,_T("动态库已经变了字符串")); if (iVal == 1) return 1; else
return 2; }
---- 2、在FileView中，从Source Files中双击 Setup00.def，在代码; Explicit exports can go here的下一行输入: Test @1

---- 3、选择成Release版本，从 Build 菜单上选择 Build Setup00.dll即可。

二、在 InstallShield 中使用实例：

---- 1、在 Setup Files Pane 中的 Language Independent\Operating System Independent下用 Insert Files 命令添入 Setup00.dll 。这样，你的动态库就可以在制作安装盘时被压入 _user1.cab 中，

---- 如果你没有把DLL放至_user1.cab中，你可以把DLL和你的应用程序放到一块，然后从目标系统中调用。但是，如果你已经做了，你必须指明你要使用的DLL的位置以使安装程序能够找到。而且你必须确信在调用DLL之前它已经被拷贝到预定目录之下。

---- 2、在脚本程序的程序段中，添加下面代码：

 // 声明setp00.dll中的Test函数原型：
prototype INT Setup00.Test( STRING,INT);
---- //如果想要在DLL中改变字符串值，需要将STRING声明成按指针传递，如下：
 //prototype INT Setup00.Test( BYREF
STRING,INT); STRING szDLL, svString; INT nValue; POINTER psvString; BOOL bDone;
NUMBER nResult; program szDLL = DLL_FILE; /*--------------------------------------*\
* Load SETUP00.DLL into memory. \*--------------------------------------*/ nResult
= UseDLL (szDLL); if (nResult = 0) then MessageBox ("动态库调入内存成功!", INFORMATION);
else MessageBox ("动态库调入内存失败!", INFORMATION); abort; endif; AskText("请输入示例字符串：",
"这是示例字符串", svString); nValue = StrLength(svString); nResult = Test(svString,nValue);
// 显示调用Setup00.dll中Test函数后的字符串 SprintfBox(INFORMATION, "调用动态库", " 调用后的字符串为：%s
", svString); if (UnUseDLL (szDLL) < 0) then MessageBox("卸载动态库失败,仍在内存中!", SEVERE);
else MessageBox("从内存中卸载动态库成功!", INFORMATION); endif;
三、请使用下面参数类型对照表，在原型声明和外部函数之间进行数据类型匹配。

---- 在安装程序调用动态库函数时需要遵循三个规则：

---- 1、动态库函数的名字最长为33个字符；InstallShield函数名最长为80个字符。

---- 2、InstallShield在调用DLL时，不能接受组合参数(就是说一个大于由个字节的参数)，然而参数可以是一个指向组合结构的指针。

---- 3、在16位平台上应调用16位DLL；而在32位平台上应调用32位DLL。

---- 本例在 WIN98，Visual C++5.0，Visual C++6.0，InstallShield5.1中调用通过。


在installshield中实现ODBC注册、序列号、防拷贝等

奇文共享,pb+sql anywhere的单机版,包括odbc注册,序列号校验,防拷贝校验等等

////////////////////////////////////////////////////////////////////////////////
//
// IIIIIII SSSSSS
// II SS InstallShield (R)
// II SSSSSS (c) 1996-1997, InstallShield Software Corporation
// II SS (c) 1990-1996, InstallShield Corporation
// IIIIIII SSSSSS All Rights Reserved.
//
//
// This code is generated as a starting setup template. You should
// modify it to provide all necessary steps for your setup.
//
//
// File Name: Setup.rul
//
// Description: InstallShield script
//
// Comments: This template script performs a basic setup on a
// Windows 95 or Windows NT 4.0 platform. With minor
// modifications, this template can be adapted to create
// new, customized setups.
//
////////////////////////////////////////////////////////////////////////////////

// Include header file
#include "sdlang.h"
#include "sddialog.h"

////////////////////// string defines ////////////////////////////

#define UNINST_LOGFILE_NAME "Uninst.isu"

//////////////////// installation declarations ///////////////////

// ----- DLL prototypes -----

// your DLL prototypes

// ---- script prototypes -----

// generated
prototype ShowDialogs();
prototype MoveFileData();
prototype HandleMoveDataError( NUMBER );
prototype ProcessBeforeDataMove();
prototype ProcessAfterDataMove();
prototype SetupRegistry();
prototype SetupFolders();
prototype CleanUpInstall();
prototype SetupInstall();
prototype SetupScreen();
prototype CheckRequirements();
prototype DialogShowSdWelcome();
prototype DialogShowSdLicense();
prototype DialogShowSdRegisterUserEx();
prototype DialogShowSdAskDestPath();
prototype DialogShowSdSelectFolder();
prototype DialogShowSdFinishReboot();

// your prototypes

// ----- global variables ------

// generated
BOOL bWinNT, bIsShellExplorer, bInstallAborted, bIs32BitSetup;
STRING svDir;
STRING svName, svCompany, svSerial;
STRING svDefGroup;
STRING szAppPath;
STRING svSetupType;

// your global variables

///////////////////////////////////////////////////////////////////////////////
//
// MAIN PROGRAM
//
// The setup begins here by hiding the visible setup
// window. This is done to allow all the titles, images, etc. to
// be established before showing the main window. The following
// logic then performs the setup in a series of steps.
//
///////////////////////////////////////////////////////////////////////////////
program
Disable( BACKGROUND );

CheckRequirements();

SetupInstall();

SetupScreen();

if (ShowDialogs()＜0) goto end_install;

if (ProcessBeforeDataMove()＜0) goto end_install;

if (MoveFileData()＜0) goto end_install;

if (ProcessAfterDataMove()＜0) goto end_install;

if (SetupRegistry()＜0) goto end_install;

if (SetupFolders()＜0) goto end_install;

end_install:

CleanUpInstall();

// If an unrecoverable error occurred, clean up the partial installation.
// Otherwise, exit normally.

if (bInstallAborted) then
abort;
endif;

endprogram

///////////////////////////////////////////////////////////////////////////////
// //
// Function: ShowDialogs //
// //
// Purpose: This function manages the display and navigation //
// the standard dialogs that exist in a setup. //
// //
///////////////////////////////////////////////////////////////////////////////
function ShowDialogs()
NUMBER nResult;
begin

Dlg_Start:
// beginning of dialogs label

Dlg_SdWelcome:
nResult = DialogShowSdWelcome();
if (nResult = BACK) goto Dlg_Start;

Dlg_SdLicense:
nResult = DialogShowSdLicense();
if (nResult = BACK) goto Dlg_SdWelcome;

Dlg_SdRegisterUserEx:
nResult = DialogShowSdRegisterUserEx();
if (nResult = BACK) goto Dlg_SdLicense;

Dlg_SdAskDestPath:
nResult = DialogShowSdAskDestPath();
if (nResult = BACK) goto Dlg_SdRegisterUserEx;

Dlg_SdSelectFolder:
nResult = DialogShowSdSelectFolder();
if (nResult = BACK) goto Dlg_SdAskDestPath;

return 0;

end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: ProcessBeforeDataMove //
// //
// Purpose: This function performs any necessary operations prior to the //
// actual data move operation. //
// //
///////////////////////////////////////////////////////////////////////////////
function ProcessBeforeDataMove()
STRING svLogFile;
NUMBER nResult;
begin

InstallationInfo( @COMPANY_NAME, @PRODUCT_NAME, @PRODUCT_VERSION, @PRODUCT_KEY );

svLogFile = UNINST_LOGFILE_NAME;

nResult = DeinstallStart( svDir, svLogFile, @UNINST_KEY, 0 );
if (nResult ＜ 0) then
MessageBox( @ERROR_UNINSTSETUP, WARNING );
endif;

szAppPath = TARGETDIR; // TODO : if your application .exe is in a subdir of TARGETDIR then add subdir

if ((bIs32BitSetup) && (bIsShellExplorer)) then
RegDBSetItem( REGDB_APPPATH, szAppPath );
RegDBSetItem( REGDB_APPPATH_DEFAULT, szAppPath ^ @PRODUCT_KEY );
RegDBSetItem( REGDB_UNINSTALL_NAME, @UNINST_DISPLAY_NAME );
endif;

// TODO : update any items you want to process before moving the data
//

return 0;
end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: MoveFileData //
// //
// Purpose: This function handles the data movement for //
// the setup. //
// //
///////////////////////////////////////////////////////////////////////////////
function MoveFileData()
NUMBER nResult, nDisk;
begin

nDisk = 1;
SetStatusWindow( 0, "拷贝系统文件" );
Disable( DIALOGCACHE );
Enable( STATUS );
StatusUpdate( ON, 100 );
nResult = ComponentMoveData( MEDIA, nDisk, 0 );

HandleMoveDataError( nResult );

Disable( STATUS );

return nResult;

end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: HandleMoveDataError //
// //
// Purpose: This function handles the error (if any) during the move data //
// operation. //
// //
///////////////////////////////////////////////////////////////////////////////
function HandleMoveDataError( nResult )
begin

switch (nResult)
case 0:
return 0;
default:
SprintfBox( SEVERE, @TITLE_CAPTIONBAR, @ERROR_MOVEDATA, nResult );
bInstallAborted = TRUE;
return nResult;
endswitch;

end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: ProcessAfterDataMove //
// //
// Purpose: This function performs any necessary operations needed after //
// all data has been moved. //
// //
///////////////////////////////////////////////////////////////////////////////
function ProcessAfterDataMove()
STRING szReferenceFile;
begin

// TODO : update self-registered files and other processes that
// should be performed after the data has been moved.

// DeinstallSetReference specifies a file to be checked before
// uninstallation. If the file is in use, uninstallation will not proceed.

szReferenceFile = svDir ^ @PRODUCT_KEY; // TODO : If your file is in a subdir of svDir add that here
DeinstallSetReference( szReferenceFile );

return 0;
end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: SetupRegistry //
// //
// Purpose: This function makes the registry entries for this setup. //
// //
///////////////////////////////////////////////////////////////////////////////
function SetupRegistry()
NUMBER nResult;
begin
RegDBSetDefaultRoot ( HKEY_LOCAL_MACHINE );
if(RegDBKeyExist ("Software\\ODBC")＜0) then
RegDBCreateKeyEx ("Software\\ODBC\\" ,"");
RegDBCreateKeyEx ("Software\\ODBC\\ODBC.INI" ,"");
RegDBCreateKeyEx ("Software\\ODBC\\ODBCINST.INI" ,"");
RegDBCreateKeyEx ("Software\\ODBC\\ODBCINST.INI\\ODBC Drivers" ,"");
RegDBCreateKeyEx ("Software\\ODBC\\ODBCINST.INI\\Sybase SQL Anywhere 5.0" ,"");
endif;
if (RegDBKeyExist("Software\\ODBC\\ODBCINST.INI\\Sybase SQL Anywhere 5.0")＜0) then
RegDBCreateKeyEx ("Software\\ODBC\\ODBCINST.INI\\Sybase SQL Anywhere 5.0" ,"");
endif;
RegDBSetKeyValueEx ( "Software\\ODBC\\ODBCINST.INI\\Sybase SQL Anywhere 5.0" , "Driver" , REGDB_STRING , svDir+"\WOD50T.DLL", -1);
RegDBSetKeyValueEx ( "Software\\ODBC\\ODBCINST.INI\\Sybase SQL Anywhere 5.0" , "Setup" , REGDB_STRING , svDir+"\WOD50T.DLL ", -1);
RegDBSetKeyValueEx ( "Software\\ODBC\\ODBCINST.INI\\ODBC Drivers" , "Sybase SQL Anywhere 5.0" , REGDB_STRING , "Installed" , -1);
RegDBSetDefaultRoot ( HKEY_CURRENT_USER );
if(RegDBKeyExist("Software\\ODBC\\ODBC.INI\\Wpl")＜0) then
if(RegDBKeyExist("Software\\ODBC\\ODBC.INI")＜0) then
if(RegDBKeyExist("Software\\ODBC")＜0) then
RegDBCreateKeyEx ("Software\\ODBC","");
endif;
RegDBCreateKeyEx ("Software\\ODBC\\ODBC.INI","");
endif;
RegDBCreateKeyEx ("Software\\ODBC\\ODBC.INI\\Wpl","");
else
RegDBDeleteKey ("Software\\ODBC\\ODBC.INI\\Wpl");
RegDBCreateKeyEx ("Software\\ODBC\\ODBC.INI\\Wpl","");
endif;
if(RegDBKeyExist("Software\\ODBC\\ODBC.INI\\ODBC Data Sources")＜0) then
RegDBCreateKeyEx ("Software\\ODBC\\ODBC.INI\\ODBC Data Sources","");
endif;
RegDBSetKeyValueEx ( "Software\\ODBC\\ODBC.INI\\Wpl", "AutoStop" , REGDB_STRING , "Yes" , -1);
RegDBSetKeyValueEx ( "Software\\ODBC\\ODBC.INI\\Wpl", "DatabaseFile" , REGDB_STRING , TARGETDIR+"\wpl.db" , -1);
RegDBSetKeyValueEx ( "Software\\ODBC\\ODBC.INI\\Wpl", "DatabaseName" , REGDB_STRING , "Wpl" , -1);
RegDBSetKeyValueEx ( "Software\\ODBC\\ODBC.INI\\Wpl", "Driver" , REGDB_STRING , TARGETDIR+"\WOD50T.DLL" , -1);
RegDBSetKeyValueEx ( "Software\\ODBC\\ODBC.INI\\Wpl", "PWD" , REGDB_STRING , "sql" , -1);
RegDBSetKeyValueEx ( "Software\\ODBC\\ODBC.INI\\Wpl", "Start" , REGDB_STRING ,TARGETDIR+"\dbeng50.exe -Q" , -1);
RegDBSetKeyValueEx ( "Software\\ODBC\\ODBC.INI\\Wpl", "UID" , REGDB_STRING ,"dba" , -1);
RegDBSetKeyValueEx ( "Software\\ODBC\\ODBC.INI\\ODBC Data Sources", "Wpl" , REGDB_STRING ,"Sybase SQL Anywhere 5.0" , -1);
RegDBSetDefaultRoot ( HKEY_CURRENT_USER );
if(RegDBKeyExist("Software\\教材管理")＜0) then
RegDBCreateKeyEx("Software\\教材管理","");
else
RegDBDeleteKey ("Software\\教材管理");
RegDBCreateKeyEx ("Software\\教材管理","");
endif;
RegDBSetKeyValueEx("Software\\教材管理","WPLDir",REGDB_STRING ,TARGETDIR, -1);
// TODO : Add all your registry entry keys here
//
//
// RegDBCreateKeyEx, RegDBSetKeyValueEx....
//

return 0;
//nResult=CreateRegistrySet("");

//return nResult;
end;

///////////////////////////////////////////////////////////////////////////////
//
// Function: SetupFolders
//
// Purpose: This function creates all the folders and shortcuts for the
// setup. This includes program groups and items for Windows 3.1.
//
///////////////////////////////////////////////////////////////////////////////
function SetupFolders()
number nResult;
begin

AddFolderIcon ( FOLDER_DESKTOP ,"教材管理系统",TARGETDIR+"\\book.exe", TARGETDIR , TARGETDIR+"\\BITMAPS\\BOOK.ICO",0,"" , REPLACE );
AddFolderIcon ( FOLDER_PROGRAMS^"教材管理系统","教材管理", TARGETDIR+"\\book.exe", TARGETDIR , TARGETDIR+"\\BITMAPS\\BOOK.ICO",0,"" , REPLACE );
// TODO : Add all your folder (program group) along with shortcuts (program items)
//
//
// CreateProgramFolder, AddFolderIcon....
//
// Note : for 16-bit setups you should add an uninstaller icon pointing to
// your log file. Under 32-bit this is automatically done by Windows.
//nResult=CreateShellObjects("")
return nResult;
end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: CleanUpInstall //
// //
// Purpose: This cleans up the setup. Anything that should //
// be released or deleted at the end of the setup should //
// be done here. //
// //
///////////////////////////////////////////////////////////////////////////////
function CleanUpInstall()
begin

if (bInstallAborted) then
return 0;
endif;

DialogShowSdFinishReboot();

if (BATCH_INSTALL) then // ensure locked files are properly written
CommitSharedFiles(0);
endif;

return 0;
end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: SetupInstall //
// //
// Purpose: This will setup the installation. Any general initialization //
// needed for the installation should be performed here. //
// //
///////////////////////////////////////////////////////////////////////////////
function SetupInstall()
begin

Enable( CORECOMPONENTHANDLING );

bInstallAborted = FALSE;

if (bIs32BitSetup) then
svDir = PROGRAMFILES ^ @COMPANY_NAME ^ @PRODUCT_NAME;
else
svDir = PROGRAMFILES ^ @COMPANY_NAME16 ^ @PRODUCT_NAME16; // use shorten names
endif;

TARGETDIR = svDir;

SdProductName( @PRODUCT_NAME );

Enable( DIALOGCACHE );

return 0;
end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: SetupScreen //
// //
// Purpose: This function establishes the screen look. This includes //
// colors, fonts, and text to be displayed. //
// //
///////////////////////////////////////////////////////////////////////////////
function SetupScreen()
begin
Enable( FULLWINDOWMODE );
Enable(INDVFILESTATUS);
SetTitle( "教材管理系统安装", 24, WHITE );

SetTitle( "教材管理系统安装", 0, BACKGROUNDCAPTION ); // Caption bar text.

Enable( BACKGROUND );

Delay( 1 );
end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: CheckRequirements //
// //
// Purpose: This function checks all minimum requirements for the //
// application being installed. If any fail, then the user //
// is informed and the setup is terminated. //
// //
///////////////////////////////////////////////////////////////////////////////
function CheckRequirements()
NUMBER nvDx, nvDy, nvResult;
STRING svResult;

begin

bWinNT = FALSE;
bIsShellExplorer = FALSE;

// Check screen resolution.
GetExtents( nvDx, nvDy );

if (nvDy ＜ 480) then
MessageBox( @ERROR_VGARESOLUTION, WARNING );
abort;
endif;

// set 'setup' operation mode
bIs32BitSetup = TRUE;
GetSystemInfo( ISTYPE, nvResult, svResult );
if (nvResult = 16) then
bIs32BitSetup = FALSE; // running 16-bit setup
return 0; // no additional information required
endif;

// --- 32-bit testing after this point ---

// Determine the target system's operating system.
GetSystemInfo( OS, nvResult, svResult );

if (nvResult = IS_WINDOWSNT) then
// Running Windows NT.
bWinNT = TRUE;

// Check to see if the shell being used is EXPLORER shell.
if (GetSystemInfo( OSMAJOR, nvResult, svResult ) = 0) then
if (nvResult ＞= 4) then
bIsShellExplorer = TRUE;
endif;
endif;

elseif (nvResult = IS_WINDOWS95 ) then
bIsShellExplorer = TRUE;

endif;

end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: DialogShowSdWelcome //
// //
// Purpose: This function handles the standard welcome dialog. //
// //
// //
///////////////////////////////////////////////////////////////////////////////
function DialogShowSdWelcome()
NUMBER nResult;
STRING szTitle, szMsg;
begin

szTitle = "教材管理MIS安装";
szMsg = "教材管理系统";
nResult = SdWelcome( szTitle, szMsg );

return nResult;
end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: DialogShowSdLicense //
// //
// Purpose: This function displays the license agreement dialog. //
// //
// //
///////////////////////////////////////////////////////////////////////////////
function DialogShowSdLicense()
NUMBER nResult;
STRING szTitle, szMsg, szQuestion, szLicenseFile;
begin

szLicenseFile = SUPPORTDIR ^ "license.txt";
szTitle = "";
szMsg = "";
szQuestion = "";
nResult = SdLicense( szTitle, szMsg, szQuestion, szLicenseFile );

return nResult;
end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: DialogShowSdRegisterUserEx //
// //
// Purpose: This function displays the user registration dialog. //
// //
// //
///////////////////////////////////////////////////////////////////////////////
function DialogShowSdRegisterUserEx()
NUMBER nResult;
STRING szTitle, szMsg;
begin

svName = "";
svCompany = "";
szTitle ="";
szMsg = "";
start:
nResult=SdRegisterUserEx( szTitle , szMsg , svName , svCompany , svSerial );
if (svSerial != "12345678910")&&(nResult = NEXT) then
MessageBox( "您录入的注册码不正确！", WARNING );
goto start;
else
return nResult;
endif;

end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: DialogShowSdAskDestPath //
// //
// Purpose: This function asks the user for the destination directory. //
// //
///////////////////////////////////////////////////////////////////////////////
function DialogShowSdAskDestPath()
NUMBER nResult;
STRING szTitle, szMsg;
begin
szTitle = "系统安装路径";
szMsg = "\n\n管理系统马上开始安装";
nResult=SdWelcome(szTitle,szMsg);
svDir="c:\\教材管理\\教材管理\\";
szMsg=szMsg+"\n\n请不要更改系统安装路径,程序中有绝对路径";
szMsg=szMsg+"\n\n如果更改路径,程序将不能正常运行!";
nResult = SdAskDestPath( szTitle, szMsg, svDir, 0 );
TARGETDIR = svDir;

return nResult;
end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: DialogShowSdSelectFolder //
// //
// Purpose: This function displays the standard folder selection dialog. //
// //
// //
///////////////////////////////////////////////////////////////////////////////
function DialogShowSdSelectFolder()
NUMBER nResult;
STRING szTitle, szMsg;
begin

if (svDefGroup = "") then
svDefGroup = @FOLDER_NAME;
endif;

szTitle = "";
szMsg = "";
nResult = SdSelectFolder( szTitle, szMsg, svDefGroup );

return nResult;
end;

///////////////////////////////////////////////////////////////////////////////
// //
// Function: DialogShowSdFinishReboot //
// //
// Purpose: This function will show the last dialog of the product. //
// It will allow the user to reboot and/or show some readme text. //
// //
///////////////////////////////////////////////////////////////////////////////
function DialogShowSdFinishReboot()
NUMBER nResult, nDefOptions;
STRING szTitle, szMsg1, szMsg2, szOption1, szOption2;
NUMBER bOpt1, bOpt2;
begin

if (!BATCH_INSTALL) then
bOpt1 = FALSE;
bOpt2 = FALSE;
szTitle = "安装完成";
szMsg1 = "教材管理系统已安装完成";
szMsg2 = "不必重起电脑即可运行.";
szOption1 = "";
szOption2 = "";
nResult = SdFinish( szTitle, szMsg1, szMsg2, szOption1, szOption2, bOpt1, bOpt2 );
return 0;
endif;

nDefOptions = SYS_BOOTMACHINE;
szTitle = "";
szMsg1 = "";
szMsg2 = "";
nResult = SdFinishReboot( szTitle, szMsg1, nDefOptions, szMsg2, 0 );

return nResult;
end;

// --- include script file section ---

#include "sddialog.rul"
在pb接口处
string GetDir
GetDir=""
RegistryGet("HKEY_CURRENT_USER\SoftWare\教材管理","WPLDir",RegString!,GetDir)
if GetDir="" then
messagebox("严重错误","您将不能正常运行本系统,必需重装系统!")
return
else
.....
end if


InstallShield Express使用簡介

InstallShield Express使用簡介(二)

返回索引 返回

本篇是延續了InstallSheild Express，在上篇中沒有提到關於Delphi中一些資料庫的連接設定，本篇中將以補足，現在Delphi 到了3.01版，InstallShield 也有作中文化，但本篇仍以英文版舉例。首先回顧產生了一個InstallShield 的Project 會有如圖一的選單：

圖一
本篇的重點是Select InstallShield Objects for Delphi和 Make Registry Changes兩個。首先勾 Select InstallShield Objects for Delphi的General Options會出現如圖二

圖二
我們以要連接至MS SQL Server 6.5為例子，並且採用SQL Links連接方式，所以BDE和SQL Links都要勾。然後就要分別設定；再勾BDE時就會出現如圖三

圖三
BDE Installation Type可以選擇Full BDE Installation 和Partial BDE Installation，如果選第一個，所有的BDE Driver 都安裝， 和Query Engine Types也安裝。如果選第二個的話，以下就可選擇所需要的Driver，本例只選Paradox Driver 和SQL Engine，再選下一步，會出現圖四：

圖四
在此畫面就可以加入BDE Aliases，本例中加入Equipment和localeqp兩個Alias，再選下一步，出現圖五

圖五
此處要決定CFG給16位元和32位元的應用程式使用，本例是for WIN95所以不選，再下一步如圖六：

圖六
在此畫面上有數個條件要填或選，以本例而言，Alias Name有兩個Equipment和 localeqp，以Equipment而言，是連SQL Server，在Path不填，而Type選MSSQL，在List any optional parameters for the aliases below中可以填入原來利用BDE Admin中要設定參數，如此不必在Client端再利用BDE Admin重新設定。如果是local database的話，PATH就需要填。再下一步出現如圖七，就完成了此部份。

圖七
再回到圖二，勾選SQL Links會出現如圖八

圖八
到此處，有關資料庫基本設定已經完成，但是有關一些BDE系統設定必須修改registry，所以必須再選圖二上的Make Registry Changes的Keys，會出現如圖九：

圖九
此時，可以按Registry Editor鈕啟動 regedit.exe，如圖十：

圖十
，在按Add Key鈕，出現如圖十一

圖十一
填入New Key，如圖十一中的值即可，再回到圖九，選Registry-Values，出現圖十二：

圖十二
以本例是要修改一個 registry value，LANGDRIVER，在按如圖十二的Add Value鈕會出現圖十三

圖十三
如圖十三，加入LANGDRIVER和”taiwan”就可以結束registry修改的部份。
如此有關Delphi的資料庫連結的部份就完成了，至於要完成一個InstallShield的Project，請在參照第66期中心通訊。