2016-07-13 21 views
0

を使用して、ODBCCP32.DLLから関数SQLGetPrivateProfileStringを使用しますはどのようにデルファイ

Calling SQLDataSourcesそれは、直接レジストリに突っついなしDSNエントリのリストを取得する方法を示してい

これまでのところ、Delphiでは問題ありません。ところで、Windows 7でDelphi 2007を使用しています。

MS Accessデータベースを参照するエントリだけを選択したいので、例に数行追加するようにしました。

まず私は、この宣言:RetBuf

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

:その後、私はどこかの例の途中で次の行を追加

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.S.同様の質問を "comp.lang.pascal.delphi.databases"ニュースグループにクロスポストしました。

+0

正確に何が問題なのでしょうか。コードにバグがありますが、コードを表示していないか、デバッグを行っているように見えることさえあります。 –

+0

はDelphiのバージョンを指定します。 –

+0

「PChar」が「PAnsiChar」のDelphi 2007以前では、表示された宣言はOKですが、Delphi 2009+ではOKではありません。ここで 'PChar' PWideCharです。 'SQLGetPrivateProfileString()'はUnicode文字列を受け付けません。Ansi文字列だけを受け入れるので、 'PChar'の代わりに' PAnsiChar'を明示的に使うべきです。 –

答えて

0

ありがとうございました。はい、私はユーザーがデータベースファイル(* .MDBまたは* .ACCDB)を選択できるように、つまり任意のデータベースに接続する前に、これをプログラム用に使用する予定です。 SQLGetPrivateProfileString関数について:特に引数lpszDefaultのために混乱しました。私は、この引数のために空の文字列を与えるだけで十分であることに気付きました。リクエストに応じて、私は以下のコードを追加します(いくつかの詳細は削除されています)。 Delphiのバージョンが2007より高い場合は、いくつかのことを適用する必要があります。

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; 
関連する問題