Autor Beitrag
OlafSt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 452
Erhaltene Danke: 83

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: Mi 13.06.18 13:35 
Hallo Freunde,

ich versuche gerade, die Liste an installierten ODBC-Treibern auszulesen. Dazu gibt es in ODBCCP32.DLL die prima Routine

BOOL SQLGetInstalledDrivers(
LPTSTR lpszBuf,
WORD cbBufMax,
WORD * pcbBufOut);

Meine Delphi-Übersetzung:
ausblenden Delphi-Quelltext
1:
function SQLGetInstalledDriversW(lpszBuf:PChar; cbufMax: word; pcbBufOut: PWord): boolean; external 'ODBCCP32.DLL';					


Rufe ich das nun auf, gibt es einen Stack Overflow:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
   Buf: string;
   Res: Word;
begin
     Setlength(Buf, 2000);
     Res:=0;
     SQLGetInstalledDriversW(PChar(Buf), 2000, Res);
end;

Auch wenn ich @Res als letzten Parameter nehme, wenn ich PAnsiChar verwende etcpp... Stets gibts einen Stack Overflow.

Was mache ich falsch ?

_________________
Lies, was da steht. Denk dann drüber nach. Dann erst fragen.
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6275
Erhaltene Danke: 118

Windows 7 + Windows 10
Tokyo Prof + CE
BeitragVerfasst: Mi 13.06.18 13:56 
Zunächst muss noch stdcall eingebaut werden:
ausblenden Delphi-Quelltext
1:
function SQLGetInstalledDriversW(lpszBuf:PChar; cbufMax: word; pcbBufOut: PWord): boolean; stdcallexternal 'ODBCCP32.DLL';					

Danach wie folgt:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var
   Buf: PChar; //string;
   Res: Cardinal;
begin
  GetMem(Buf, 2000);
  Res:=0;
  SQLGetInstalledDriversW(Buf, 2000, @Res);
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2039
Erhaltene Danke: 376

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 14.06.18 01:28 
Guten Abend OlafSt,

die Funktion nennt sich SQLGetInstalledDrivers und nicht SQLGetInstalledDriversW:

function SQLGetInstalledDriversW(...): Boolean; stdcall; external 'ODBCCP32.DLL'// stdcall hat außerdem gefehlt

So wird die Funktion nicht gefunden!
Wenn du darauf bestehst, die Funktion anders zu benennen, dann muss der eigentliche Funktionsname explizit angegeben werden:

ausblenden Delphi-Quelltext
1:
function SQLGetInstalledDriversW(...): Boolean; stdcall; external 'ODBCCP32.DLL' name 'SQLGetInstalledDrivers';					

So würde es bei mir aussehen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
function SQLGetInstalledDrivers(lpszBuf: PChar; cbBufMax: Word; pcbBufOut: PWord): Boolean; stdcallexternal 'ODBCCP32.DLL';

// Aufruf
var
  buf: array[0..MAX_PATH - 1of Char; // MAX_PATH = 260 ... 260 Zeichen sollten ausreichen.
  bufSize: Word;
begin
  ZeroMemory(@buf, Length(buf)); // buf initialisieren
  bufSize := 0;  // bufSize initialisieren

  SQLGetInstalledDrivers(@buf, Length(buf), @bufSize);
  ShowMessage(buf);
  ShowMessage(IntToStr(bufSize));
end;

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6275
Erhaltene Danke: 118

Windows 7 + Windows 10
Tokyo Prof + CE
BeitragVerfasst: Do 14.06.18 09:31 
Sehr interessant, dass es SQLGetInstalledDriversW nicht geben soll.
Ich frage mich dann, wieso mein Beispiel-Code ein sinnvolles Ergebnis geliefert hat.
OlafSt Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 452
Erhaltene Danke: 83

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: Do 14.06.18 15:51 
SQLGetInstalledDrivers() liefert die Ergebnisse als AnsiChar zurück. Für Unicode wurde dann SQLGetInstalledDriversW() dazugefügt.

Darum bekam ich auch bei @Frühlingsrolle's Beispiel einen Haufen chinesische Zeichen zurück, die keinen Sinn ergaben (ja, ich kann das in begrenztem Umfang lesen). An sich hatte ich es schon fast, auf das stdcall; kam ich nur nicht.

Das ganze sieht also fertig so aus:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
uses Winapi.Windows, Vcl.Dialogs, System.SysUtils;

function SQLGetInstalledDriversW(lpszBuf:PChar; cbufMax: word; pcbBufOut: PWord): boolean; stdcallexternal 'ODBCCP32.DLL';

procedure GetODBCDriver;
var
   Buf: array[0..2000of Char;
   bufSize: word;
   Res: Cardinal;
begin
     ZeroMemory(@buf, Length(buf));
     bufSize:=0;
     SQLGetInstalledDriversW(@Buf, Length(buf), @bufSize);
     ShowMessage(IntToStr(bufSize));
     ShowMessage(buf);
end;


Das ganze liefert eine Liste der installierten ODBC-Treiber zurück. Jeder ODBC-Treibername ist mit einem 0-Byte abgeschlossen, das Ende der Liste mit zwei 0-Bytes in Folge. Ergo wird MAXPATH, das IIRC 260 beträgt, bei weitem nicht reichen (ich habe hier bereits 844 Bytes).

Aber: Frage beantwortet, danke für die Hilfe !

_________________
Lies, was da steht. Denk dann drüber nach. Dann erst fragen.
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2039
Erhaltene Danke: 376

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Do 14.06.18 19:31 
In der Doku steht nichts über eine Unicode Version (SQLGetInstalledDriversW)! Und explizit danach gesucht, komm ich auf kein Suchergebnis! Daher bin ich ausgegangen, dass es diese Funktion nicht gibt. Verlinkt sie mir, solltet ihr sie finden. ;)

Trotzdem, wenn es funktioniert, passt es doch.

Nachtrag

In der Headerdatei (obdcinst.h) sind beide Versionen vorzufinden:

ausblenden C++-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
BOOL INSTAPI SQLGetInstalledDrivers
(
    _Out_writes_(cchBufMax) LPSTR lpszBuf,  // LPSTR = PAnsiChar
    WORD  cchBufMax,
    WORD* pcchBufOut
);

BOOL INSTAPI SQLGetInstalledDriversW
(
    _Out_writes_(cchBufMax) LPWSTR lpszBuf,  // LPWSTR = PWideChar
    WORD  cchBufMax,
    WORD* pcchBufOut
);

Der Typ PChar ergibt bei:
< D2009 - PAnsiChar
>= D2009 - PWideChar

Da meine Übersetzung für die Ansi-Version gedacht war, und mit PChar unter Delphi Tokio (beim TE) lief, wurde daraus ein PWideChar, und daher auch die "chinesischen Zeichen".
Damit solche Fehler nicht passieren, und die Funktion mit alten und neuen Delphi-Versionen keine Probleme mit sich bringt, wäre es am besten so zu lösen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
// Variante 1

{$IFNDEF UNICODE}
function SQLGetInstalledDrivers(lpszBuf: PAnsiChar; cchBufMax: Word; pcchBufOut: PWord): Boolean; stdcallexternal 'ODBCCP32.DLL' name 'SQLGetInstalledDrivers';
{$ELSE}
function SQLGetInstalledDrivers(lpszBuf: PWideChar; cchBufMax: Word; pcchBufOut: PWord): Boolean; stdcallexternal 'ODBCCP32.DLL' name 'SQLGetInstalledDriversW';
{$ENDIF}

// Variante 2

const
  {$IFNDEF UNICODE}
  SQL_GET_INSTALLED_DRIVERS = 'SQLGetInstalledDrivers'
  {$ELSE}
  SQL_GET_INSTALLED_DRIVERS = 'SQLGetInstalledDriversW'
  {$ENDIF}

function SQLGetInstalledDrivers(lpszBuf: PChar; cchBufMax: Word; pcchBufOut: PWord): Boolean; stdcallexternal 'ODBCCP32.DLL' name SQL_GET_INSTALLED_DRIVERS;

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6275
Erhaltene Danke: 118

Windows 7 + Windows 10
Tokyo Prof + CE
BeitragVerfasst: Fr 15.06.18 07:26 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
In der Doku steht nichts über eine Unicode Version (SQLGetInstalledDriversW)! Und explizit danach gesucht, komm ich auf kein Suchergebnis! Daher bin ich ausgegangen, dass es diese Funktion nicht gibt. Verlinkt sie mir, solltet ihr sie finden.

In der MSDN-Doku kann ich auch nichts dazu finden. Aber Tante Google spuckt einiges dazu aus.
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2039
Erhaltene Danke: 376

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Fr 15.06.18 15:10 
Zeig mal, was Tante Google zu SQLGetInstalledDriversW! ausspuckt.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6275
Erhaltene Danke: 118

Windows 7 + Windows 10
Tokyo Prof + CE
BeitragVerfasst: Mo 18.06.18 07:21 
Ich glaube, du bist schon groß und kannst das ganz alleine.
Aber zwei kleine Tipps:
1. "Meintest Du: SQLGetInstalledDrivers" ignorieren.
2. Bei den Ergebnissen nicht nur die Überschriften lesen.
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2039
Erhaltene Danke: 376

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Mo 18.06.18 08:53 
Ich behaupte, du bist größer, schöner und schlauer. Daher wird es für dich kein Problem sein, genau 1 Suchergebnis zu SQLGetInstalledDriversW hier zu verlinken, welches ungleich diesem Topic entspricht.
Deine Tipps werde ich beherzigen und in Ehren halten.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
jasocul
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 6275
Erhaltene Danke: 118

Windows 7 + Windows 10
Tokyo Prof + CE
BeitragVerfasst: Mo 18.06.18 09:11 
user profile iconFrühlingsrolle hat folgendes geschrieben Zum zitierten Posting springen:
welches ungleich diesem Topic entspricht.

Meinst du, weil das Topic "SQLGetInstalledDrivers in Delphi" heißt?
Ich habe mich halt eher an den Source im ersten Beitrag gehalten. Dort geht es dann doch um SQLGetInstalledDriversW.
Aber hier mal ein Link, der sich mit der WideChar-Variante auseinandersetzt:
www.pinvoke.net/defa...GetInstalledDriversW
Das war übrigens der erste Treffer in der Liste.