오라클 데이터 소스 이름 목록을 가져 와서 콤보 박스에 추가하여 연결할 데이터 소스를 선택할 수 있습니까? TNS_NAMES.ora 파일의 내용을 읽고 데이터 소스 이름을 얻는 프로그램이 필요합니다. 필자는 FileSearch를 수행 할 수 있지만 프로그램이 다른 컴퓨터에서 실행되고 Oracle 클라이언트가 다른 폴더에 설치 될 수 있으므로 TOAD, PL/SQL 개발자 및 기타 Oracle 관리자와 같은 TNS_NAMES 파일 자체를 찾는 프로그램이 필요합니다.델파이에서 tnsnames.ora 파일을 어떻게 파싱 할 수 있습니까?
답변
TNS_NAMES.ora
파일 안에 포함 된 데이터 소스 또는 기타 정보를 얻으려면이 파일을 구문 분석해야합니다. 따라서 먼저이 파일의 구문 규칙을 here 및 here에서 읽은 다음 가장 일반적인 방법을 사용하여 정규식을 사용하여이 파일을 구문 분석 할 수 있습니다. 불행히도 Delphi 2010 RTL에는 정규 표현식에 대한 지원이 포함되어 있지 않습니다. 하지만 PCRE library을 사용할 수 있습니다.) 여기에서 자신의 델파이 구현을 작성하기 위해이 기사를 가이드로 사용할 수 있습니다.
TNSNames Reader
당신은 당신의 형태와 링크 FormCreate와 Button1Click이라 이벤트에 오라클 10. 드롭 콤보 상자와 버튼이 코드를 사용할 수 있습니다
(C#을)
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.
특히 코드의 주석 처리가 제거 된 경우 코드 전용 답변은 일반적으로 권장되지 않습니다. 답에 몇 가지 의견이나 설명을 추가해 주시겠습니까? –
덧글에 .. –
죄송합니다. 나는 러시아 출신이다. –
고관절. 그 많은 도움이 –
정규 표현식은 구문 분석을위한 매우 잘못된 도구입니다. –