How I can parse a tnsnames.ora file from delphi?
How can I get the list of Oracle data source names and add them to a combobox so that I can choose whcich datasource to connect to? I need the program to read the contents of the TNS_NAMES.ora file and get the data source names. I can do a FileSearch but want the program to find the TNS_NAMES file itself like TOAD,PL/SQL developer and other Oracle managers do, as the program will be run on different computers and Oracle client might be ins开发者_如何学运维talled into different folders.
To get the datasource or any other information contained inside of the TNS_NAMES.ora
file you must parse this file. So first read the Syntax Rules for this file from here and here, and then you can use the most common approach to parse these files, which is use regular expressions. Unfortunally the Delphi 2010 RTL doesn't include support for regular expressions. But you can use the PCRE library). from here you can use as guide these articles to write your own delphi implementation.
TNSNames Reader
(C#)- Parsing tnsnames.ora using regex (C#)
You can use this code for Oracle 10. Drop combobox and button on your form and link FormCreate and button1click events.
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.
精彩评论