作者:毕照杰([email protected]
前年在一个网站作版主的时候,应网友的要求,我写了一篇文章,《如何把应用程序程序和ORACLE客户端一起打包》,说明如何制作ORACLE客户端,后边本来是要附加上如何用程序来配置ORACLE连接串的(一般的用户是用NET CONFIG或net assistant来手工配置),因为比较懒散,一直没有写,今天补上,同时为了大家阅读方便,我把《如何把应用程序程序和ORACLE客户端一起打包》这篇文章也写在一起,希望能给大家带来帮助。
一、如何打包ORACLE客户端。
我们在做程序的时候,经常会需要安装ORACLE的客户端,如果客户终端非常多的时候,这就会是一项很麻烦的工作,一方面要安排我们的应用程序,另一方面要安装RACLE客户端,而且还要对ORACLE客户端进行NET EASY配置,真是不胜其烦。
经过研究,我做到了可以把ORACLE客户端和应用程序一起打包,又自己用程序来配置NET EASY。
1、打包要知道的问题:
A、要打包哪些文件。
B、如何修改注册表。
C、如何设置环境变量。
D、打包使用哪些工具。
2、打包要使用的文件:
我们先找一个装有ORACLE的机器,把以下的文件打包。为了保证ORACLE能正常访问,我们需要保持原目录结构不变。
A、$ORACLE_HOME\BIN下边所有DLL,IMP.EXE,EXP.EXE,SQLPLUS.EXE,SQLPLUSW.EXE。($ORACLE_HOME指的是ORACLE的主目录,比如D:\ORACLE\ORA8I)。
B、$ORACLE_HOME\network目录下的三个目录:Admin、mesg、tnsapi,把它们全部打包。
C、$ORACLE_HOME\ocommon\nls目录。
D、$ORACLE_HOME\oracore\mesg目录。
E、$ORACLE_HOME\sqlplus下的两个目录:admin、mesg。
3、如何修改注册表:
为不麻烦,我们可以把这个装有ORACLE的机器的注册表里边ORACLE信息照搬过来。全部照抄。
4、如何设置环境变量:
设置环境变量,我们要在PATH前边加上$ORACLE_HOME\BIN;
5、使用哪些打包工具:
我个人比较喜欢的工具是WiseInstaller,它的功能很强大,能导入整个文件目录(我感觉这一点比Install shilled要好)、导入注册表、也可以设置环境变量,以及设置NT服务等等(我好象是给它做广告似的)。
我们现在就可以使用它来做我们的客户端了。
第一步,先把我说的这些文件目录全部导入到我们的安装工程中去。
第二步,找到设置注册表选项,导入注册表中HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE下边所有的注册表值。
第三步,找到环境变量设置选项,在它的PATH那里加上$ORACLE_HOME\BIN。这里的$ORACLE_HOME用<Installdir>来代替。
做完这一切,编译,发布,OK。
6、如何用手工来修改NET EASY。
现在我们已经做完了这个安装包,并且把它安装到了我们的电脑上边,那么,在开始菜单上是没有ORACLE这个选项的,如何设置ORACLE NET EASY呢?
我们现在暂时可以这样做:
打开我们的ORACLE客户端的安装目录,找到NETWORK\ADMIN子目录下边的tnsnames.ora这个文件,直接对它进行编辑就行了。
比如,我们现在想配置一个叫做NTSERVER的服务名,我们就可以这样写:
NTSERVER =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 机器名)(PORT = 端口号))
)
(CONNECT_DATA =
(SERVICE_NAME = 全局数据库名)
)
)
然后,直接把它加到tnsnames.ora这个文件的后边就行了。
如果NTSERVER这个服务名已经存在的话,我们可以直接修改它的机器名、
端口号和全局数据库名就可以了。

解决方案 »

  1.   

    作者:毕照杰([email protected]
    前年在一个网站作版主的时候,应网友的要求,我写了一篇文章,《如何把应用程序程序和ORACLE客户端一起打包》,说明如何制作ORACLE客户端,后边本来是要附加上如何用程序来配置ORACLE连接串的(一般的用户是用NET CONFIG或net assistant来手工配置),因为比较懒散,一直没有写,今天补上,同时为了大家阅读方便,我把《如何把应用程序程序和ORACLE客户端一起打包》这篇文章也写在一起,希望能给大家带来帮助。
    二、如何用程序来配置ORACLE数据库连接
    1、更改的参数
    我们知道,ORACLE把数据库的连接信息都保存在tnsnames.ora这个文件里边的,所以我们可以手工更改这个文件来连接数据库,由于现在的版本一般都采用TCL/IP来连接数据库,那对我们来说,一般只要更改几个地方就可以了:
    A、数据库连接名,比如前边的NTSERVER。
    B、机器名(或IP)。
    C、端口号,默认是1521,也有其它端口的。
    D、全局数据库名。
    2、文件的位置
    一般来说,这个文件是放在当前$ORACLE_HOME/network/admin下边,如果在本机上装有多个数据库,则有多个这样的文件,最好一起更改,可以通过注册表来查找当前有几个ORACLE目录。我们通过HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\ ALL_HOMES\HOME_COUNTER可以看出ORACLE的个数。
    当然,也有比较省力一点的作法,就是把$ORACLE_HOME/network/admin下的tnsnames.ora这个文件放到当前的可执行程序的目录下,则在执行程序的时候,应用程序的连接会以当前目录下的tnsnames.ora的配置为准。
    3、具体作法
    A、在当前目录下放一个临时文件,tnsname.sql,内容如下:
    %S =
    (DESCRIPTION =
    (ADDRESS_LIST =
    (ADDRESS = (PROTOCOL = TCP)(HOST = %s)(PORT = %d))
    )
    (CONNECT_DATA =
    (SERVICE_NAME = %s)
    )
    )
    B、程序写法(DELPHI语言)1)取得ORACLE个数
    function OracleCount: Integer;
    var
    OraNum: Integer;
    reg: TRegistry;
    begin
    OraNum := 0;
    Reg := TRegistry.Create;
    try
    reg.RootKey := HKEY_LOCAL_MACHINE;
    if Reg.OpenKey('SOFTWARE\ORACLE\ALL_HOMES', True) then
    begin
    //这里考虑有多个数据库的情况。
    OraNum := StrToInt(Reg.ReadString('HOME_COUNTER'));
    end;
    Reg.CloseKey;
    Result := OraNum;
    finally
    Reg.Free;
    end;
    end;2)取得单个ORACLE目录
    function GetOraHome(HomeIndex: Integer): string;
    var
    reg: TRegistry;
    OraHome: string;
    begin
    Reg := TRegistry.Create;
    try
    reg.RootKey := HKEY_LOCAL_MACHINE;
    if Reg.OpenKey('SOFTWARE\ORACLE\ALL_HOMES\ID' + IntToStr(HomeIndex), True)
    then
    begin
    //这里考虑有多个数据库的情况。
    OraHome := Reg.ReadString('PATH');
    if Copy(OraHome, Length(OraHome), 1) = '\' then
    Delete(OraHome, length(OraHome), 1);
    end;
    Reg.CloseKey;
    Result := OraHome;
    finally
    Reg.Free;
    end;
    end;3)设置单个ORACLE连接
    procedure SetLink(OraFile: string; LinkName: string; Host: string; Port:
    Integer; DbName: string);
    var
    FileVar: TextFile;
    Str: string;
    CanCopy: Boolean; //看是否可以COPY
    TnsFile, TmpFile, SqlFile: string;
    Num: Integer;
    LastStr: string;
    begin
    CanCopy := True;
    try
    SqlFile := '' + CurDir + '\tnsnames.sql' + '';
    TnsFile := '' + OraFile + '';
    TmpFile := '' + CurDir + '\tnsnames.tmp' + '';
    Num := 0;//先把本地的一个TMP文件写一下。使它等于连接字符串
    AssignFile(FileVar, SqlFile);
    Reset(FileVar);
    while not Eof(FileVar) do
    begin
    Num := Num + 1;
    ReadLn(FileVar, Str);
    //注意,这里用大写来区分,以下两个都是小写
    if (pos('%S', Str) > 0) then
    Str := Format(Str, [LinkName]);
    if (pos('%s', Str) > 0) and (pos('%d', Str) > 0) then
    Str := Format(Str, [Host, Port]);
    if (pos('%s', Str) > 0) and not (pos('%d', Str) > 0) then
    Str := Format(Str, [DbName]);
    if Num = 1 then
    TraceLog(TmpFile, Str, 'r')
    else
    TraceLog(TmpFile, Str, 'a');
    end;
    CloseFile(FileVar);//读取旧的TNSNAMES.ORA,把它写入到本地的TMP文件中。
    AssignFile(FileVar, TnsFile);
    if FileExists(TnsFile) then
    Append(FileVar)
    else
    ReWrite(FileVar);
    Reset(FileVar);
    while not Eof(FileVar) do
    begin
    ReadLn(FileVar, Str);
    lastStr := Str;
    if not (pos(LinkName + ' =', UpperCase(Str)) > 0) and CanCopy
    and not (pos('#', Str) > 0) then
    TraceLog(TmpFile, Str, 'a');
    if pos(LinkName + ' =', UpperCase(Str)) > 0 then
    CanCopy := False;
    if (CanCopy = False) and (Trim(Str) = '') then
    CanCopy := True;
    end;
    CloseFile(FileVar);
    //如果是空格,则不用写入,否则,写一行空格在最后
    if Trim(LastStr) <> '' then
    TraceLog(TmpFile, '', 'a');AssignFile(FileVar, TmpFile);
    Reset(FileVar);
    TraceLog(TnsFile, '# Edited by Bi ZhaoJie ' +
    FormatDateTime('yyyy-mm-dd hh:mm:ss', now), 'R');
    TraceLog(TnsFile, '', 'a');
    while not Eof(FileVar) do
    begin
    ReadLn(FileVar, Str);
    TraceLog(TnsFile, Str, 'a');
    end;
    CloseFile(FileVar);
    //结束写tnsnames.ora
    except
    end;
    end;4)写文本文件
    procedure TraceLog(FileName: string; str: string; WriteType: string);
    var
    FileVar: TextFile;
    sss: string;
    begin
    sss := '' + FileName + '';
    AssignFile(FileVar, sss);
    try
    if UpperCase(WriteType) = 'R' then
    ReWrite(FileVar)
    else
    begin
    if FileExists(sss) then
    Append(FileVar)
    else
    ReWrite(FileVar);
    end;
    Writeln(FileVar, Str);
    CloseFile(FileVar);
    except
    ShowMsg('File can not open,check if it is readonly!');
    end;
    end;
    5)程序最终实现
    for i := 0 to OracleCount - 1 do
    begin
    FileName := GetOraHome(i) + '\network\admin\tnsnames.ora';
    SetLink(FileName, 连接串名, 数据库服务器, 端口,
    全局数据库名);
    end;