一个朋友拿来一套软件,让我帮着做一个安装程序,这套软件是用Delphi开发的,其中用到了BDE,因此要求把BDE也一起打包安装。
我没用过BDE,更加不熟悉BDE的组成,刚开始不知道如何下手。由于我习惯使用InnoSetup来制作安装程序,便想到在InnoSetup的网站上也许有相关的介绍。于是登录InnoSetup的网站,在FAQ中找到了解决办法,现总结一下:
一、首先,在InnoSetup的网站上下载BdeInst.cab、MiniReg.exe、AddAlias.exe三个程序,其中BdeInst.cab就是BDE的安装包,其中只包含BdeInst.dll一个文件,有3兆多,将它提取出来。
二、将BdeInst.dll、MiniReg.exe、AddAlias.exe与要安装的应用程序放在一起。
三、在制作好的InnoSetup脚本中的相关节中加入以下内容:
[Files]
Source: "BdeInst.dll"; DestDir: "{tmp}"
Source: "MiniReg.exe"; DestDir: "{tmp}"
Source: "AddAlias.exe"; DestDir: "{tmp}"
[Run]
Filename: "{tmp}\MiniReg.exe"; Parameters: """{tmp}\BdeInst.dll"""
Filename: "{tmp}\AddAlias.exe"; Parameters: """Alias SubDir Driver"""
经过这样的改动,制作出来的Setup.exe就可以将应用程序连同BDE一块安装了。
之所以要用到MiniReg.exe和AddAlias.exe,是因为BdeInst.dll其实是一个COM组件,拷贝到用户机器上以后还需要注册一下才能用,MiniReg.exe就是做这个工作的,它的功能类似RegSvr32(不明白为什么不直接使用RegSvr32), MiniReg.exe是用Delphi编写的,源程序很短,顺便列在下面:
// FileName: MiniReg.dpr
program MiniReg;
{
MiniReg v1.0 by Jordan Russell
Note: For Delphi 3+, you'll need to change "OLE2" below to "ActiveX".
}
uses
Windows, OLE2; // ActiveX
{x$R *.RES}
procedure RegisterServer(const Filename: String);
var
LibHandle: THandle;
RegisterServerProc: function: HRESULT; stdcall;
begin
LibHandle := LoadLibrary(PChar(Filename));
if LibHandle <> 0 then
try
@RegisterServerProc := GetProcAddress(LibHandle, 'DllRegisterServer');
if Assigned(@RegisterServerProc) then
RegisterServerProc;
finally
FreeLibrary(LibHandle);
end;
end;
begin
if ParamCount <> 1 then
Exit;
CoInitialize(nil);
try
RegisterServer(ParamStr(1));
finally
CoUninitialize;
end;
end.
AddAlias的作用是向BDE注册一个别名,指向要连接的数据库(类似ODBC的数据源),它运行时需要三个命令行参数,分别是:别名、子目录名、驱动名。AddAlias也是用Delphi写的,源代码如下:
// FileName: AddAlias.dpr
program AddAlias;
{
program adds a alias to the BDE configuration file
parameters:
0: programname + path (standard parameter of OS)
1: Name of alias
if begins with '-' then delete first if exist
else do nothing if exist
2: path to data directory
3: BDE driver name
Bugfix: Savierhs Lopez Arteaga 3.1.2001
AddAlias didn't delete alias with beginning '-'
}
uses
Windows, SysUtils, BDE;
var
GAlias: string = 'New';
GDriver: string = szPARADOX;
GAliasDir: string;
FParams: string;
FDrvName: string;
FDelete: boolean;
i: integer;
function StrToOem(const AnsiStr: string): string;
begin
SetLength(Result, Length(AnsiStr));
if Length(Result) > 0 then
CharToOem(PChar(AnsiStr), PChar(Result));
end;
begin
for i := 1 to ParamCount do
begin
case i of
1: GAlias := ParamStr(1);
2: GAliasDir := ParamStr(2);
3: GDriver := ParamStr(3);
end;
end;
//default alias
if GAliasDir = '' then GAliasDir := ExtractFilePath(ParamStr(0))+'Data';
//should delete alias first? separate alias name
if GAlias[1] = '-' then
begin
FDelete := True;
//GAlias := Copy(GAlias, 1, Length(GAlias)); Bug
Delete(GAlias, 1, 1); //Fix by Savierhs Lopez Artega
end else FDelete := False;
FDrvName := GDriver;
//set Parameters, the driver and server name
if (CompareText(GDriver, szCFGDBSTANDARD) = 0) or
(CompareText(GDriver, szPARADOX) = 0) or
(CompareText(GDriver, szDBASE) = 0) or
(CompareText(GDriver, szFOXPRO) = 0) or
(CompareText(GDriver, szASCII) = 0) then
begin
if (CompareText(GDriver, szCFGDBSTANDARD) = 0) then FDrvName := szPARADOX;
//set parameters for the new alias
FParams := Format('%s:"%s"', [szCFGDBPATH, GAliasDir]) +
Format(';%s:"%s"', [szCFGDBDEFAULTDRIVER, GDriver]) +
Format(';%s:"%s"', [szCFGDBENABLEBCD, szCFGFALSE]);
end else begin
if (CompareText(GDriver, 'INTRBASE') = 0)
then FParams := Format('%s:"%s"', [szSERVERNAME, GAliasDir])
else FParams := Format('%s:"%s"', [szDATABASENAME, GAliasDir]);
//add other Parameters here !!!!!!!!!!!!!!!!!
end;
DbiInit(nil);
try
if FDelete then
try
DbiDeleteAlias(nil, PChar(GAlias));
except
end;
try
DbiAddAlias(nil, PChar(StrToOem(GAlias)),
PChar(StrToOem(FDrvName)),
PChar(FParams), True);
DbiCfgSave(nil, nil, True);
except
end;
finally
DbiExit();
end;
end.
杂感:
一、InnoSetup这个安装制作工具非常好用,它短小精致、公开源码、无需注册可免费使用,能满足绝大多数需要,我经常向人建议抛弃InstallShield这个庞然大物,使用InnoSetup。
二、原来的印象中,BDE也是个庞然大物,有10兆之巨,但这次的安装包只有3兆,很出乎意料。