如何获取 Oracle 数据源名称列表并将它们添加到组合框,以便我可以选择连接到哪个数据源?我需要程序读取 TNS_NAMES.ora 文件的内容并获取数据源名称。我可以进行文件搜索,但希望程序像 TOAD、PL/SQL 开发人员和其他 Oracle 管理器一样找到 TNS_NAMES 文件本身,因为程序将在不同的计算机上运行,并且 Oracle 客户端可能安装到不同的文件夹中。
问问题
1984 次
2 回答
3
要获取文件中包含的数据源或任何其他信息,TNS_NAMES.ora
您必须解析此文件。所以首先从这里和这里阅读这个文件的语法规则,然后你可以使用最常见的方法来解析这些文件,即使用正则表达式。不幸的是,Delphi 2010 RTL 不包括对正则表达式的支持。但是您可以使用PCRE 库)。从这里您可以使用这些文章作为指导来编写您自己的 delphi 实现。
TNSNames Reader
(C#)- 使用正则表达式(C#)解析 tnsnames.ora
于 2011-08-12T16:25:13.153 回答
1
您可以将此代码用于 Oracle 10。将组合框和按钮拖放到表单上并链接 FormCreate 和 button1click 事件。
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Registry, Vcl.StdCtrls;
type
TForm1 = class(TForm)
ComboBox1: TComboBox;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure ParseTNS;
public
{ Public declarations }
end;
var
Form1: TForm1;
slTNSConfig : TStringList;
implementation
{$R *.dfm}
function GetTNSNamesPath : string;
var
Reg: TRegistry;
SubKeyNames: TStringList;
Name: string;
begin
Reg := TRegistry.Create;
Try
Reg.RootKey := HKEY_LOCAL_MACHINE;
Reg.OpenKeyReadOnly('SOFTWARE\ORACLE');
SubKeyNames := TStringList.Create;
Try
Reg.GetKeyNames(SubKeyNames);
for Name in SubKeyNames do
// oracle 10 save path to ORACLE_HOME in registry key like this
// HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraClient10g_home1\ORACLE_HOME
// for oracle 8 and 9 another key
if pos('KEY_',Name)=1 then
begin
Reg.OpenKeyReadOnly(Name);
// for oracle 10 path to tnsnames.ora like this
// %ORACLE_HOME%\NETWORK\ADMIN\tnsnames.ora
// for oracle 8 and 9 another path
Result :=Reg.ReadString('ORACLE_HOME')+'\NETWORK\ADMIN\tnsnames.ora';
end;
Finally
SubKeyNames.Free;
End;
Finally
Reg.Free;
End;
end;
procedure TForm1.ParseTNS;
var
slTemp : TStringList;
sPath, sTemp : string;
i : integer;
begin
slTemp:= TStringList.Create;
slTNSConfig:= TStringList.Create;
try
sPath:=GetTNSNamesPath;
if (length(sPath)<33) or (not FileExists(sPath)) then
messageDlg('tnsnames.ora not found.', mtError, [mbOk],0)
else
begin
slTemp.LoadFromFile(sPath); // Load tnsnames.ora
sTemp := StringReplace(StringReplace(UpperCase(slTemp.Text),' ','',[rfReplaceAll]),')','',[rfReplaceAll]); // delete ')' and spaces
slTemp.Clear;
slTemp.Delimiter:='(';
slTemp.DelimitedText:=sTemp; // parse like Name=Value
sTemp:='';
for i := 0 to slTemp.Count-1 do
begin
if pos('DESCRIPTION',slTemp[i])=1 then // Get Name before description
begin
sTemp:=StringReplace(slTemp[i-1],'=','',[rfReplaceAll]);
ComboBox1.Items.Add(sTemp); // Fill combobox
end;
if length(slTemp.ValueFromIndex[i])>0 then //Get filled Name=Value
slTNSConfig.Add(sTemp+'_'+slTemp[i]); // Fill TNS config like TNS_HOST=Value
end;
ComboBox1.Sorted:=true;
end;
finally
slTemp.Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ComboBox1.Text:='';
ParseTNS;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
sHost, sPort, sSID, sServiceName : string;
begin
sHost:=slTNSConfig.Values[ComboBox1.Text+'_HOST'];
sPort:=slTNSConfig.Values[ComboBox1.Text+'_PORT'];
sSID:=slTNSConfig.Values[ComboBox1.Text+'_SID'];
sServiceName:=slTNSConfig.Values[ComboBox1.Text+'_SERVICE_NAME'];
messageDLG('sHost:'+sHost+' sPort:'+sPort+' sSID:'+sSID+' sServiceName:'+sServiceName,mtInformation,[mbOk],0);
end;
end.
于 2015-04-17T18:33:51.037 回答