Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Active Directory - Abfrage (https://www.delphipraxis.net/167785-active-directory-abfrage.html)

Maya 18. Apr 2012 10:53

Datenbank: Active Directory • Version: ?? • Zugriff über: Delphi 2010

Active Directory - Abfrage
 
Hallo ihr Lieben,

unsere Admins kamen auf die Idee, da ich ja in meinen Postbuch unsere Mitarbeiter abspeichern möchte, ich die doch immer aktuell aus dem Active Directory abfragen könnte. Tolle Idee, muss ich zugeben, wenn da nicht das Problem der Abfrage wäre.

Wenn ich in meinen Testprogramm auf einen Button klicke, soll er mir einfach mal alle Leutz in einen Memo darstellen.

Delphi-Quellcode:
  DataModule2.qry1.Close;
  DataModule2.con1.Close;
  DataModule2.con1.Open;
  DataModule2.qry1.Open; //< DA KNALLT'S!
  DataModule2.qry1.First;

  while not DataModule2.qry1.Eof do
    begin
      mmo1.Lines.Add(DataModule2.qry1.FieldByName('displayname').AsString);
      DataModule2.qry1.Next;
    end;
In der Query ist folgender Text:

Code:
SELECT top 10(*) FROM 'LDAP:\\*****.lan'
Die Verbindung kann er ja scheinbar aufbauen, aber die Abfrage funktioniert nicht, da meint er immer, dass mindestens ein Fehler vorhanden ist.

Wie muss die Domäne z.B. aussehen? Wir sind hier uns alle ein wenig unsicher, ob die so richtig ist, wie wir sie uns dachten und probierten schon mehrere Sachen aus. Könnt ihr mal ein Beispiel nennen?

Danke, das Maya

s.h.a.r.k 18. Apr 2012 11:12

AW: Active Directory - Abfrage
 
Was genau für eine Fehlermeldung erscheint denn?

Maya 18. Apr 2012 11:29

AW: Active Directory - Abfrage
 
"Exception-Klasse EOleException mit Meldung 'Der Befehlt enthielt mindestens einen Fehler'."

Hab's auch schon mit "DC=***,DC=lan" probiert und da kommt die gleiche Fehlermeldung.

Uwe Raabe 18. Apr 2012 12:24

AW: Active Directory - Abfrage
 
Was für eine Komponente verbirgt sich denn hinter qry1?

Maya 18. Apr 2012 12:25

AW: Active Directory - Abfrage
 
Übrigens, ich benutze die ADO-Komponenten für die Query und die Connection.

Uwe Raabe 18. Apr 2012 12:31

AW: Active Directory - Abfrage
 
Versuch's mal mit "/" anstatt "\".

Maya 18. Apr 2012 12:59

AW: Active Directory - Abfrage
 
Leider klappt das auch nicht. -.-

Mit dem Active Directory Explorer habe ich keine Probleme, mir die ganzen Strukturen und Einträge anzusehen. Also habe ich zumindest Leserechte darauf.

Maya 18. Apr 2012 13:16

AW: Active Directory - Abfrage
 
Sry für Doppelpost.

Also, maybe habe ich das Problem ein klein wenig eingeschränkt?
Ich hab den Quelltext mal ein wenig abgewandelt.

Delphi-Quellcode:
procedure TForm1.btn2Click(Sender: TObject);
begin
  DataModule2.con1.Close;
  DataModule2.con1.Open;

  Datamodule2.qry1.Close;
  DataModule2.qry1.SQL.Clear;
  datamodule2.qry1.SQL.Add('SELECT TOP 10 (*) FROM ''LDAP:\\DC=****,DC=lan''');
  DataModule2.qry1.Open; //< Wieder knallt es HIER! 
  DataModule2.qry1.First;

  while not DataModule2.qry1.Eof do
    begin
      mmo1.Lines.Add(DataModule2.qry1.FieldByName('displayname').AsString);
      DataModule2.qry1.Next;
    end;
end;
Wenn es knallt, dann kommt diesmal aber ein klein wenig anderer Fehler:
Zitat:

Exception-Klasse EAccessViolation mit Meldung 'Zugriffsverletzung bei Adresse 004F844B in Modul 'TestADO.exe'."

generic 18. Apr 2012 13:25

AW: Active Directory - Abfrage
 
Schau dir mal im Internet nach ADSI und Delphi.
Da gibt es paar super Webseiten zu.

Maya 18. Apr 2012 13:30

AW: Active Directory - Abfrage
 
Zitat:

Zitat von generic (Beitrag 1162528)
Schau dir mal im Internet nach ADSI und Delphi.
Da gibt es paar super Webseiten zu.

Darauf kam ich auch schon, aber hilft mir nicht wirklich weiter bei meinen Problem, außer du findest eine entsprechende Lösung für mich.

Uwe Raabe 18. Apr 2012 13:45

AW: Active Directory - Abfrage
 
Zitat:

Zitat von Maya (Beitrag 1162522)
Delphi-Quellcode:
  datamodule2.qry1.SQL.Add('SELECT TOP 10 (*) FROM ''LDAP:\\DC=****,DC=lan''');
  DataModule2.qry1.Open; //< Wieder knallt es HIER!

Die Syntax für die LDAP-Query lautet nach einem Beispiel von Microsoft so (siehe "//" statt "\\"):

Delphi-Quellcode:
SELECT title, telephoneNumber From 'LDAP://DC=Microsoft, DC=COM' WHERE
objectClass='user' AND objectCategory='Person'
Ich würde es erst mal mit einer sehr ähnlichen Select-Anweisung versuchen, um den Fehler einzugrenzen (Vielleicht versteht AD kein "TOP 10").

Ebenso könnte es daran liegen, daß ohne die WHERE-Klausel, keine sinnvollen RecordSets zurückgegeben werden können, da diese eventuell nicht alle die gleichen Felder haben. Es steckt eben keine homogene Tabelle dahinter.

Maya 19. Apr 2012 05:54

AW: Active Directory - Abfrage
 
Tut mir Leid, dass ich gestern nicht mehr antwortete. Hatte dann dreiviertel vier Feierabend und hatte zu Hause selber einiges zutun.

Wir haben das jetzt soweit gepackt, dass zwar immer noch eine Zugriffsverletzung kommt, wenn ich aber auf "Fortfahren" gehe, zeigt der mir im Memo einiges an Daten an, was danach auch aussieht, was ich haben möchte.
Das Problem liegt da, wie Uwe schon vermutete, dass die AD mit dem "Top 10(*)", geschweige denn überhaupt dem Sternchen zurecht kommt. Man muss scheibar explizit angeben, was für Spalten man haben möchte. Darauf muss erstmal einer kommen. ;)
Ohne WHERE-Klausel habe ich es jetzt noch nicht versucht, da ich mir nicht das Memo sprengen möchte.

Der Quelltext sieht jetzt wie folgt aus:

Delphi-Quellcode:
procedure TForm1.btn2Click(Sender: TObject);
var LastErrorIndex, NativeError, NumberError, i: Integer;
    SourceError, DescriptionError, SQLStateError: string;
begin
  try
    DataModule2.con1.Close;
    DataModule2.con1.Open;

    with DataModule2.qry1 do
      begin
        Close;
        SQL.Text:='SELECT displayName FROM ''LDAP://DC=****,DC=lan'' WHERE objectClass=''user'' AND objectCategory=''Person''';
        Open; //<Hier liegt scheinbar immer noch ein Problem.
        First;
      end;

    mmo1.Lines.Clear;

    while not DataModule2.qry1.Eof do
      begin
        mmo1.Lines.Add(DataModule2.qry1.FieldByName('displayName').AsString);
        DataModule2.qry1.Next;
      end;
  except
    for I := 0 to DataModule2.con1.Errors.Count - 1 do
      begin
        LastErrorIndex:=i;
        SourceError:=DataModule2.con1.Errors.Item[LastErrorIndex].Source;
        NumberError:=DataModule2.con1.Errors.Item[LastErrorIndex].Number;
        DescriptionError:=DataModule2.con1.Errors.Item[LastErrorIndex].Description;
        SQLStateError:=DataModule2.con1.Errors.Item[LastErrorIndex].SQLState;
        NativeError:=DataModule2.con1.Errors.Item[LastErrorIndex].NativeError;
        Showmessage('SourceError: '+ SourceError+#10#13+
                    'NumberError: '+IntToStr(NumberError)+#10#13+
                    'DescriptionError: '+DescriptionError+#10#13+
                    'SQLStateError: '+SQLStateError+#10#13+
                    'NativeError: '+IntToStr(NativeError));
      end;
  end;
end;
Wir hatten diesen Code gefunden, um Fehler abgezufangen und ggf. etwas genauer zu erfahren, wo der Fehler ist. Das hat soweit auch ganz gut geholfen. Aber bei der Zugriffsverletzung handelt sich ja um ein delphiseitiges Problem und weniger bei der AD, oder?

Jumpy 19. Apr 2012 08:09

AW: Active Directory - Abfrage
 
Also '*' sollte schon noch funktionieren. Aber viel mehr nicht, sprich diverse SQL-Funktionen, die man von den üblichen Datenbanken kennt, oder aber komplexere Abfragen funktionieren nicht.

Was die Zugriffsverletzung angeht: Kannst du da nicht mal einen Haltepunkt setzen und sehen, wo genau die passiert, innerhalb des Query.Open passiert ja auch noch was.

Maya 19. Apr 2012 08:29

AW: Active Directory - Abfrage
 
Also ich hab das mit dem Sternchen versucht und es klappte leider nicht. Gut, finde ich aber jetzt wo ich es weiß, nicht all zu schlimm.

Ich habe bei dem "Close" einen Haltepunkt gesetzt und mit F7 weitergemacht. Aber bei dem Sprung von "SQl.Text" zu "SQL.Open" kommt die Fehlermeldung der Zugriffsverletzung.

"Im Projekt TestADO.exe iste ine Exception der Klasse EAccessViolation mit der Meldung 'Zugriffsverletzung bei Adresse 004FFAE3 in Modul 'TestADO.exe'.Lesen von Adresse 00000000' aufgetreten."

Es macht mich nur skeptisch, warum er dann nicht in den EXCEPT-Teil springt, sondern einfach weiter macht, als wäre nix gewesen und auch die Abfrage ausführt.
Ich habe zwischenzeitlich auch vor dem "Open" noch ein "Active:=True" eingebaut. Da sprach er bei der Zugriffsverletzung immer auf diese Zeile.

Wir vermuten mittlerweile, ob es nicht doch ein Bug der Komponenten sein könnte?

NACHTRAG
Wenn ich den SQL-Text in die Query eingebe, dann klappt es tadellos. Verstehen muss ich das nicht, oder?

Uwe Raabe 19. Apr 2012 09:20

AW: Active Directory - Abfrage
 
Zitat:

Zitat von Maya (Beitrag 1162620)
Ich habe zwischenzeitlich auch vor dem "Open" noch ein "Active:=True" eingebaut. Da sprach er bei der Zugriffsverletzung immer auf diese Zeile.

Die Implementierung von TDataSet.Open ist auch nur:

Delphi-Quellcode:
procedure TDataSet.Open;
begin
  Active := True;
end;
Somit wäre die zweite der beiden Zeilen redundant und der Fehler tritt sowieso bereits in der ersten auf.

Zitat:

Zitat von Maya (Beitrag 1162620)
Wir vermuten mittlerweile, ob es nicht doch ein Bug der Komponenten sein könnte?

ADO war schon immer etwas mimosenhaft...

DeddyH 19. Apr 2012 09:20

AW: Active Directory - Abfrage
 
Aufgrund der angegebenen Speicheradresse ist es wohl so, dass irgendwo auf einen nil-Pointer (nicht vorhandenes Objekt o.ä.) zugegriffen wird. Wie das kommt, kann ich natürlich aus der Ferne auch nicht sagen.

p80286 19. Apr 2012 09:23

AW: Active Directory - Abfrage
 
Zitat:

Zitat von Maya (Beitrag 1162620)
NACHTRAG
Wenn ich den SQL-Text in die Query eingebe, dann klappt es tadellos. Verstehen muss ich das nicht, oder?

Das verstehe ich nicht, der Text wird doch hier
Delphi-Quellcode:
with DataModule2.qry1 do
      begin
        Close;
        SQL.Text:='SELECT displayName FROM ''LDAP://DC=****,DC=lan'' WHERE objectClass=''user'' AND objectCategory=''Person''';
        Open; //<Hier liegt scheinbar immer noch ein Problem.
        First;
      end;
übergeben also was machst Du da?

Und versuch es doch bitte einmal ohne "With"

Gruß
K-H

jobo 19. Apr 2012 09:40

AW: Active Directory - Abfrage
 
Vielleicht hakts am Doppelpunkt?
Mal ParamCheck abschalten=?

Maya 19. Apr 2012 09:48

AW: Active Directory - Abfrage
 
Zitat:

Zitat von p80286 (Beitrag 1162629)
Das verstehe ich nicht, der Text wird doch hier
Delphi-Quellcode:
with DataModule2.qry1 do
      begin
        Close;
        SQL.Text:='SELECT displayName FROM ''LDAP://DC=****,DC=lan'' WHERE objectClass=''user'' AND objectCategory=''Person''';
        Open; //<Hier liegt scheinbar immer noch ein Problem.
        First;
      end;
übergeben also was machst Du da?

Wenn ich die SQL-Abfrage direkt in die Query schon zur Designzeit eingebe und im Quelltext die Zuweisung auskommentiere, erscheint die Zugriffsverletzung nicht. Das meinte ich damit, habe mich vielleicht unglücklich ausgedrückt. Ohne "WITH" habe ich es auch schon ausprobiert, da ich auch schon überlegte, ob das nicht ggf. eine Sache sein könnte, die ADO nicht so mag. ;) Ergebnis war aber das gleiche.

Ich habe beim etwas genaueren googeln den Beitrag hier gefunden: http://www.delphipraxis.net/84463-ad...erletzung.html und sind jetzt am Überlegen, ob wir nicht gleich das auch so machen, dass wir die Query dynamisch erstellen.

Delphi-Quellcode:
procedure TForm1.btn1Click(Sender: TObject);
var ConString: String;
    LastErrorIndex, NativeError, NumberError, i: Integer;
    SourceError, DescriptionError, SQLStateError: string;
begin
  ConString:='Provider=ADsDSOObject;Encrypt Password=False;Mode=Read;Bind Flags=0;ADSI Flag=-2147483648';

  try
    qry2:=TADOQuery.Create(nil);
    qry2.SQL.Text:=' SELECT displayName            '+
                   ' FROM ''LDAP://DC=****,DC=lan'' '+
                   ' WHERE objectClass=''user''    '+
                   ' AND objectCategory=''Person'' ';
    qry2.Active:=False;
    qry2.ConnectionString:=ConString;
    qry2.Active:=True;
    qry2.First;

    mmo1.Lines.Clear;
    while not qry2.Eof do
      begin
        mmo1.Lines.Add(qry2.FieldByName('displayName').AsString);
        qry2.Next;
      end;
  except
    for I := 0 to qry2.Connection.Errors.Count - 1 do
      begin
        LastErrorIndex:=i;
        SourceError:=qry2.Connection.Errors.Item[LastErrorIndex].Source;
        NumberError:=qry2.Connection.Errors.Item[LastErrorIndex].Number;
        DescriptionError:=qry2.Connection.Errors.Item[LastErrorIndex].Description;
        SQLStateError:=qry2.Connection.Errors.Item[LastErrorIndex].SQLState;
        NativeError:=qry2.Connection.Errors.Item[LastErrorIndex].NativeError;
        Showmessage('SourceError: '+ SourceError+#10#13+
                    'NumberError: '+IntToStr(NumberError)+#10#13+
                    'DescriptionError: '+DescriptionError+#10#13+
                    'SQLStateError: '+SQLStateError+#10#13+
                    'NativeError: '+IntToStr(NativeError));
      end;
    qry2.Free;
  end;
Ich habe auch versucht, bei der Query, die ich zur Designzeit erstelle, direkt den ConnectionString einzugeben, aber hat keine positiven Ergebnisse.

Wenn noch jmd. einen Lösungsansatz hat, wäre ich dem sehr dankbar. :)


Zitat:

Zitat von jobo (Beitrag 1162630)
Vielleicht hakts am Doppelpunkt?
Mal ParamCheck abschalten=?

Welcher Doppelpunkt?

DeddyH 19. Apr 2012 09:49

AW: Active Directory - Abfrage
 
Dieser Doppelpunkt vermutlich:
Zitat:

LDAP:

Maya 19. Apr 2012 09:58

AW: Active Directory - Abfrage
 
Zitat:

Zitat von DeddyH (Beitrag 1162632)
Dieser Doppelpunkt vermutlich:
Zitat:

LDAP:

ICH LIEBE EUCH!! :lol:
Echt, das war's, jetzt klappt's perfekt.

Wenn ich das dynamisch erstelle, ist dann ParamCheck von vornherein (OMG, schreibt man das so?) auf "false" gesetzt?

p80286 19. Apr 2012 10:00

AW: Active Directory - Abfrage
 
hast du mal den debugger gefragt was in SQL.Text steht?

Gruß
K-H

Maya 19. Apr 2012 10:04

AW: Active Directory - Abfrage
 
Zitat:

Zitat von p80286 (Beitrag 1162637)
hast du mal den debugger gefragt was in SQL.Text steht?

Gruß
K-H

Nicht nur einmal und hatte eigentlich nie gesehen, dass der Text anders war, als ich ihn eingab. Deswegen verstand ich das Problem nicht. Hätte ich gesehen, dass da was anders drinne steht, hätte ich vielleicht die minimale Chance gehabt, darauf selber zu kommen. ;)
Habe jetzt ParamCheck auf "False" gestellt und nun klappt's tadellos.

Danke an alle, die halfen! Ich schlage mich jetzt weiter mit der Active Directory 'rum. :)

jobo 19. Apr 2012 10:34

AW: Active Directory - Abfrage
 
Zitat:

Zitat von DeddyH (Beitrag 1162632)
Dieser Doppelpunkt vermutlich:
Zitat:

LDAP:

Ja, wenn es jetzt klappt, meinte ich den. :lol:

DeddyH 19. Apr 2012 10:38

AW: Active Directory - Abfrage
 
Der war ja auch nicht schwer zu finden: einfach alles ausblenden, was kein Doppelpunkt ist :lol:

jobo 19. Apr 2012 10:50

AW: Active Directory - Abfrage
 
Ja für Dich!
Aber ein Hinweis auf das SQL Statement hätte nicht geschadet, im restlichen Quelltext waren ja auch noch ein paar Doppelpunkte.
Also gut, die Antwort war etwas schlampig,
Zitat:

ParamCheck
könnte man aber auch noch als Hinweis gelten lassen.

Maya 19. Apr 2012 10:53

AW: Active Directory - Abfrage
 
Zitat:

Zitat von DeddyH (Beitrag 1162644)
Der war ja auch nicht schwer zu finden: einfach alles ausblenden, was kein Doppelpunkt ist :lol:

Ich glaube, wenn man seit zwei Tagen, wenn nicht so gar schon drei Tagen auf dieses SQL-Statement starrt, dann sieht man nicht mal mehr bunte Herzchen darin, geschweige denn einen Doppelpunkt. ;)

Klappt super und langsam entsteht soetwas wie eine Freundschaft zwischen mir und der Active Directory. Man muss nur wissen, wie man sie nehmen muss. ;)

jobo 19. Apr 2012 11:02

AW: Active Directory - Abfrage
 
Zitat:

Zitat von Maya (Beitrag 1162647)
Man muss nur wissen, wie man sie nehmen muss. ;)

Wie das eben so ist mit Freundschaften.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:15 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz