2016-07-13 3 views
0

를 사용하여, odbccp32.dll에서 기능 SQLGetPrivateProfileString를 사용 :어떻게 델파이

Calling SQLDataSources이 직접 레지스트리에 파고없이 DSN 항목의 목록을 검색하는 방법을 보여줍니다

.

지금까지 Delphi에는 문제가 없었습니다. 안녕하세요, 저는 Windows 7에서 Delphi 2007을 사용하고 있습니다.

이제 MS Access 데이터베이스를 참조하는 항목 만 선택하고 싶습니다. 예제에 몇 줄을 추가하려고했습니다.

우선 나는이 선언 :

Result := SQLGetPrivateProfileString('ODBC Data Sources', Buffer1, 'Driver', RetBuf, 100, 'odbc.ini'); 

RetBuf을 가진 :

function SQLGetPrivateProfileString; external 'odbccp32.dll' name 'SQLGetPrivateProfileString'; 

가 그럼 난 예제의 중간 어딘가에 다음 줄을 추가 :

function SQLGetPrivateProfileString( 
    lpszSection, lpszEntry, lpszDefault, lpszRetBuffer: PChar; 
    cbRetBuffer: Integer; 
    lpszFilename: PChar): integer; stdcall; 

및 구현에서

PChar으로 선언되었습니다.

ODBC의 레지스트리에 표시된대로 드라이버 문자열을 검색 할 수있었습니다. GetMemFreeMem을 호출하여 RetBuf을 초기화하고 정리하면 프로그램을 안정적으로 유지하는 것이 필수적으로 보입니다.

제 질문은 : *.MDB 파일 (또는 *.ACCDB 파일) 경로를 검색하는 방법은 무엇입니까? 나는 아무 소용이 시도 : 물론

SQLGetPrivateProfileString(nil, Buffer1, 'DBQ', RetBuf, 128, 'odbc.ini') 

, 내가 SQLGetPrivateProfileString() 기능에 대한 좋은 대안에 관심이있을 것입니다.

도움을 주시면 감사하겠습니다.

P. "comp.lang.pascal.delphi.databases"뉴스 그룹에 비슷한 질문을 교차 게시했습니다.

+0

정확히 무엇이 문제입니까? 코드에 버그가 있지만 코드를 표시하지 않았거나 디버깅을하는 것처럼 보였습니다. –

+0

은 Delphi 버전을 지정합니다. 나는 유니 코드 대 ansi 문자열과 chars에 대해 오도하고 있는지 궁금합니다. –

+0

델파이 2007 이전 버전에서는'PChar'가'PAnsiChar '인데도 선언문은 OK이지만 델파이 2009+에서는'PChar' PWideChar입니다. 'SQLGetPrivateProfileString()'은 유니 코드 문자열을 허용하지 않고 Ansi 문자열 만 허용하므로 일반적으로'PChar' 대신에'PAnsiChar'를 명시 적으로 사용해야합니다. –

답변

0

모든 제안을 해주셔서 감사합니다. 예, 저는 사용자가 데이터베이스 파일 (* .MDB 또는 * .ACCDB)을 선택할 수있게 해주는 프로그램, 즉 데이터베이스에 연결하기 전에이를 사용할 계획입니다. SQLGetPrivateProfileString 함수에 관해서 : 나는 인수 lpszDefault 때문에 특히 혼란 스러웠다. 이 인수에 빈 문자열을 제공하는 것으로 충분하다는 것을 알았습니다. 요청시 아래에 코드를 추가합니다 (몇 가지 세부 정보가 제거됨). 2007 년보다 높은 Delphi 버전의 경우 몇 가지 사항을 수정해야합니다.

const 
    SQL_SUCCESS = 0; 
    SQL_NO_DATA = 100; 
    SQL_FETCH_NEXT = 1; 
    SQL_FETCH_FIRST = 2 
    SQL_MAX_DSN_LENGTH = 32; 
    SQL_MAX_OPTION_STRING_LENGTH = 256; 

procedure TForm1.Button2Click(Sender: TObject); 
var 
    EnvironmentHandle: Pointer;; 
    Buffer1: array[0..SQL_MAX_DSN_LENGTH] of Char; 
    Buffer2: array[0..SQL_MAX_OPTION_STRING_LENGTH] of Char; 
    RetBuf1, RetBuf2: PChar; 
    Len1, Len2: SmallInt; 
    DataSourceName, DriverName, PathToFile: string; 
    Result, i: Integer; 
begin 
    if SQLAllocEnv(EnvironmentHandle) = SQL_SUCCESS then 
    try 
    try 
     i := 0; 
     Result := SQLDataSources(EnvironmentHandle, SQL_FETCH_FIRST, Buffer1, SizeOf(Buffer1), Len1, Buffer2, SizeOf(Buffer2), Len2); 
     if Result = SQL_SUCCESS then 
     repeat 
     try 
      // Initialise 
      DataSourceName := ''; 
      DriverName := ''; 
      PathToFile := ''; 

      // Prepare to find out about the driver 
      SetString(DataSourceName, Buffer1, Len1); 
      GetMem(RetBuf1, 200); 
      Result := SQLGetPrivateProfileString('ODBC Data Sources', Buffer1, '', RetBuf1, 200, 'odbc.ini'); 

      // If it went well, then only show the result when it's an Access database 
      if Result > 0 then 
      begin 
      if (Pos('access', LowerCase(RetBuf1)) > 0) then 
      begin 
       // Get the driver of the current DSN entry 
       SetString(DriverName, RetBuf1, Result); 

       // Try to retrieve the path to the file 
       if (Pos('access', LowerCase(RetBuf1)) > 0) then 
       begin 
       // The Access database files are registered with key 'DBQ'    
       GetMem(RetBuf2, 200); 
       Result := SQLGetPrivateProfileString(Buffer1, 'DBQ', '', RetBuf2, 200, 'odbc.ini') 
       if Result > 0 then 
       begin 
        SetString(PathToFile, RetBuf2, Result); 
        if Pos('~', PathToFile) > 0 then PathToFile := WinapiGetLongPathName(PathToFile); 
       end; 
       FreeMem(RetBuf2); 

       // Arrange the output, if it's relevant 
       if not FileExists(PathToFile) then Continue; 
       AdvStringGrid1.Cells[0, i + 1] := DataSourceName; 
       AdvStringGrid1.Cells[1, i + 1] := DriverName; 
       AdvStringGrid1.Cells[2, i + 1] := PathToFile; 
       AdvStringGrid1.RowCount := i + 2; 
       Inc(i); 
       end; 
      end; 
      end; 

      // Prepare for the next loop 
      FreeMem(RetBuf1); 
     finally 
      Result := SQLDataSources(EnvironmentHandle, SQL_FETCH_NEXT, Buffer1, SizeOf(Buffer1), Len1, Buffer2, SizeOf(Buffer2), Len2); 
     end; 
     until (Result = SQL_NO_DATA) 

    except on E:Exception do 
     ShowMessage(E.Message); 
    end; 
    finally 
    SQLFreeEnv(EnvironmentHandle); 
    end; 
end;