开发者

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.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜