2016-07-13 52 views
0

我發現這個話題追溯到2004年:如何使用功能SQLGetPrivateProfileString從ODBCCP32.DLL,採用Delphi

Calling SQLDataSources

它顯示瞭如何檢索DSN條目列表而不直接戳進入註冊表。

到目前爲止,Delphi沒有問題。順便說一下,我在Windows 7上使用Delphi 2007.

現在,我只想選擇引用MS Access數據庫的條目,所以我試着只添加幾行到示例。

首先我聲明這一點:

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

而且正在實施:

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

RetBuf

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

然後我在這個例子中的中間位置添加以下行宣佈爲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版本。我想知道你是否被Unicode和ansi字符串和字符誤導... –

+0

對於Delphi 2007和更早版本,顯示的聲明是可以的,其中'PChar'是'PAnsiChar',但對於Delphi 2009+不適用,其中'PChar'是'PWideChar'。 'SQLGetPrivateProfileString()'不接受Unicode字符串,只接受Ansi字符串,所以你應該明確地使用'PAnsiChar'而不是'PChar'。 –

回答

0

謝謝大家的所有建議。是的,我打算將它用於允許用戶選擇數據庫文件(* .MDB或* .ACCDB)的程序,即在連接到任何數據庫之前。關於函數SQLGetPrivateProfileString:由於其參數lpszDefault,我特別困惑。我意識到給這個參數提供一個空字符串就足夠了。根據要求,我在下面添加了我的代碼(刪除了一些細節)。對於高於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;