Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Active Directory - Alle Benutzer auslesen - mit ActiveDS_TLB (https://www.delphipraxis.net/104548-active-directory-alle-benutzer-auslesen-mit-activeds_tlb.html)

cherry 6. Dez 2007 07:59


Active Directory - Alle Benutzer auslesen - mit ActiveDS_TLB
 
Hi @ all

Ich möchte eigentlich nach einem Benutzer im AD suchen, jedoch nicht nach dem "Username" sondern nach dem "Displayname" oder "Fullname". Da ich denke, dass ActiveDS_TLB keine Funktion dafür vorsieht, dachte ich: Ich lese zuerst alle Benutzer des AD aus und Suche dann nach dem "Displayname" oder "Fullname"...

Nur... wie macht man das?

Alter Mann 6. Dez 2007 08:38

Re: Active Directory - Alle Benutzer auslesen - mit ActiveDS
 
Hi cherry,

falsch gedacht. In den Beispielen von Agni Software ist auch eins für directorysearch.

Gruß

cherry 6. Dez 2007 10:48

Re: Active Directory - Alle Benutzer auslesen - mit ActiveDS
 
Hey Alter Mann...

Vielen Dank für deine schnelle Antwort, das hat mir schon "etwas" weitergeholfen. Ich schaffe es nun mit folgendem, von mir abgeändertem, AgnisoftCode eine Liste aller User zu bekommen.

Ok ich hab nun eine Liste der DisplayNames aller Benutzer, nur habe ich den Usernamen aber nicht dazu, den brauche ich jetzt auch nocht. Eine Idee?

Delphi-Quellcode:
procedure TForm1.Button4Click(Sender: TObject);
var obj : IAds;
    search : IDirectorySearch;
    tst : PWideChar;
    p : array[0..0] of PWideChar;
    cls : IADsClass;
    cont : IADsContainer;
    i : integer;
    ptrResult : THandle;
    col : ads_search_column ;
    hr : HResult;
    opt : array[0..0] of ads_searchpref_info; // has to be an array
    dwErr : DWord;
    szErr : array[0..255] of WideCHar;
    szName : array[0..255] of WideChar;
begin
   lbDsSearch.Items.CLear;
   AdsGetObject(edtDSPath.Text, IDirectorySearch, search);
   try
     p[0] := StringToOleStr('Name');
     opt[0].dwSearchPref := ADS_SEARCHPREF_SEARCH_SCOPE;
     opt[0].vValue.dwType := ADSTYPE_INTEGER;
     opt[0].vValue.Integer := ADS_SCOPE_SUBTREE;
     hr := search.SetSearchPreference(@opt[0],1);
     if (hr <> 0) then
       begin
         hr := ADsGetLastError(dwErr, @szErr[0], 254, @szName[0], 254);
         ShowMessage(WideCharToString(szErr));
         Exit;
       end;
     hr := search.ExecuteSearch('(objectCategory=User)',@p[0], 1, ptrResult);
     hr := search.GetNextRow(ptrResult);
     while (hr <> S_ADS_NOMORE_ROWS) do
     begin
        hr := search.GetColumn(ptrResult, p[0],col);
        if Succeeded(hr) then
        begin
          if col.pADsValues <> nil then
            lbDsSearch.Items.Add(col.pAdsvalues^.CaseIgnoreString);
          search.FreeColumn(col);
        end;
        Hr := search.GetNextRow(ptrResult);
     end;
   finally
   end;
end;
cheers

MarLe 6. Dez 2007 15:17

Re: Active Directory - Alle Benutzer auslesen - mit ActiveDS
 
... vielleicht hilft folgendes

Delphi-Quellcode:
...
function ADsGetObject(pwcPathName: PWideChar; const xRIID: TGUID; var pVoid): HResult; stdcall; external 'activeds.dll';
...
function TForm1.GetUserFullname(Domain, Username: String): string;
var
  usr: IADSUser;
  pc:array[0..255] of WideChar;
  s:String;
begin
  s:='WinNT://' + Domain + '/' + username;
  StringToWideChar(S,PC,Length(S)+1);

  ADsGetObject(pc, IADsUser, usr);
  if not Assigned(usr) then
    result := 'Unknown'
  else
    result := usr.FullName;
end;
Gruß MarLe

cherry 6. Dez 2007 16:34

Re: Active Directory - Alle Benutzer auslesen - mit ActiveDS
 
@MarLe

ne, eben nicht. Du hast mich wohl falsch verstanden. Ich will den Full- oder Displayname eingeben und den Username erhalten. Das ist genau das umgekehrte von dem was du mir vorgeschlagen hast. Du gibst den Username ein und erhälst den Fullname, das hab ich bereits in mein Programm implementiert.

Danke trotzdem...

noch jmd eine Idee?

Alter Mann 6. Dez 2007 17:55

Re: Active Directory - Alle Benutzer auslesen - mit ActiveDS
 
Hallo cherry,

du kommst an MSDN ran? Wenn Ja schau dir mal die Erläuterungen zu ExecuteSearch an.
Wenn Nein wirst Du warten müssen bis ein anderer Hilfestellung gibt, da ich noch nicht weiß
ob ich am Wochenende dazu komme.

Das kurze Beispiel:
Zitat:

LPWSTR pszAttr[] = { L"ADsPath", L"Name", L"samAccountName" };
ADS_SEARCH_HANDLE hSearch;
DWORD dwCount= sizeof(pszAttr)/sizeof(LPWSTR);

// Search for users with a last name that begins with "h".
hr = m_pSearch->ExecuteSearch(L"(&(objectClass=user)(sn=h*))", pszAttr, dwCount, &hSearch );

Gruß

Alter Mann 9. Dez 2007 17:19

Re: Active Directory - Alle Benutzer auslesen - mit ActiveDS
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo cherry,

habe doch noch 2-3 Stunden Zeit gefunden.
Anbei ein kleines Programm(D7) mit dem du nach beliebigen Einträgen suchen kannst.
Du solltest immer den distinguishedName mit rein nehmen, da du so bequemer
auf das Objekt zugreifen kannst.

@all

Während der Umsetzung ist mir aufgefallen, das der Import der ActiveDs_TLB nicht
richtig funktioniert, so wurde aus THandle ein Pointer bei IDirectorySearch.
Auch wurden einige Typdeklarationen, verglichen mit MSDN geändert(siehe u.a. _adsvalue).

Gibt es dafür eine Erklärung, oder ist es Bug?

Zurück zum Programm.

Die Kernfunktion ist DirectorySearch:
Delphi-Quellcode:
function TIDirectorySearchForm.DirectorySearch(Properties : Array of PWideChar;
                                               SearchText : String;
                                               Category  : String;
                                               out Items : TStringList) : Boolean;

  function Included(str1, str2 : String) : boolean;
  var
    s1, s2 : String;
  begin
    s1 := UpperCase(Str1);
    s2 := UpperCase(Str2);
    Result := POS(s1, s2) <> 0;
  end;
var
  Search   : IDirectorySearch;
  ptrResult : THandle;
  col      : ads_search_column;
  hr       : HResult;
  opt      : ads_searchpref_info;
  dwCount  : DWORD;
  dwErr    : DWord;
  szErr    : array[0..255] of WideCHar;
  szName   : array[0..255] of WideChar;
  idx      : Integer;
begin
  if SUCCEEDED(ADsGetObject(edtADsPath.Text, IDirectorySearch, Search)) then
  begin
    try
      opt.dwSearchPref  := ADS_SEARCHPREF_SEARCH_SCOPE;
      opt.vValue.dwType := ADSTYPE_INTEGER;
      opt.vValue.__MIDL_0010.Integer := ADS_SCOPE_SUBTREE;
      if not SUCCEEDED(search.SetSearchPreference(opt, 1)) then
      begin
         ADsGetLastError(dwErr, @szErr[0], 254, @szName[0], 254);
         ShowMessage(WideCharToString(szErr));
         Result := False;
         Exit;
      end;
        dwCount := Length(Properties);
        hr := search.ExecuteSearch(StringToOleStr('(objectCategory=' + Category + ')'), @Properties[0], dwCount, ptrResult);
        if SUCCEEDED(hr) then
        begin
          hr := search.GetNextRow(ptrResult);

          while (hr <> S_ADS_NOMORE_ROWS) do
          begin
             for idx := 0 to dwCount -1 do
             begin
               if Succeeded(search.GetColumn(ptrResult, Properties[idx], col)) then
               begin
                 if col.pADsValues <> nil then
                 begin
                   if Included(SearchText, col.pAdsValues^.__MIDL_0010.BackLink.ObjectName) then
                   Items.Add(col.pszAttrName + ': ' + col.pAdsValues^.__MIDL_0010.BackLink.ObjectName);
                 end;
                 search.FreeColumn(col);
               end;
             end;
             hr := search.GetNextRow(ptrResult);
          end;
        end;
    finally
    end;
  end;
  Result := Items.Count -1 <> -1;
end;
Im Grunde unterscheidet sich sich nicht groß vom Original, die Änderungen betreffen in diesem Zusammenhang
nur die Abfrage der gesuchten Eigenschaften und der damit Verbundene Zugriff auf BackLink.

Die kleine Funktion Included musste sein, da POS direkt so mit den Werten nicht wollte.

Für den Rest siehe Anhang.

Gruß

cherry 10. Dez 2007 10:56

Re: Active Directory - Alle Benutzer auslesen - mit ActiveDS
 
Hi Alter Mann

Du bist ja der Hammer, so wie du dich da ins Zeug gelegt hast. Nur leider bring ich das Programm hier nicht zum laufen. Ich kann zwar prima in der Domänenstrucktur herumnavigieren, aber der "search" Button reagiert nicht... egal aus welcher Kategorie ich suche oder was für einen Suchbegriff ich eingebe, nichts passiert. Ich wollte grade eben mal testen ob der Button in die Routine kommt, aber da fehlt mir wahrscheinlich noch ne Unit...

Ich hab schon mal gesehen dass du "ActiveDs_TLB" und "ADsHlp" verwendest. Die Unit "adsErr" ist mir aber unbekannt... Wo krieg ich die her?

Naja du hast schon so viel Aufwand betrieben, ich kann auch verstehen wenn du von einem Anfänger wie mir die Schnauze voll hast! ;-)

Alter Mann 10. Dez 2007 17:58

Re: Active Directory - Alle Benutzer auslesen - mit ActiveDS
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ups, vergessen?

Kaum, ich dachte eigentlich das sie bei Agni dabei ist.

Das mit dem Suchen sollte aber trotzdem funktionieren.

1. Bei ADs die zu durchsuchenden Domäne eintragen bzw. rechts daneben auf den SpeedButton klicken
und die Domäne auswählen.

2. Den Suchbegriff eintragen, z.B. Benutzernamen

3. Was suchen wir den Benutzer, Computer oder etwas anderes?

4. Alle zu durchsuchenden Eigenschaften(Attribute) eintragen.

5. Searching-Button anklicken.

Beispiel

1) LDAP://DC=xx,DC=xxxx,DC=xx <- Ist kein Link, wird nur so dargestellt!
2) Administrator
3) user
4) sn, displayName, distinguishedName, userPrincipalName
5) (Klick)

Wichtig ist der Zusammenhang zwischen 2, 3 und 4. Es macht keinen Sinn den Familiennamen eines Benutzer einzugeben,
die ObjectCategory user zuwählen und nur nach dem sAMAccountNamen zu suchen, der Beispielhaft aus einer Zahlenfolge
besteht.

Sollte der Compiler rum maulen das die vorhandenen Parameter den tatsächlichen Parametern entsprechen müssen
(bei GetNextRow), dann liegt es am Tyblib-Import. Die Lösung alle Pointer innerhalb von IDirctorySearch in THandle
ändern.

Gruß

cherry 18. Mär 2008 09:31

Re: Active Directory - Alle Benutzer auslesen - mit ActiveDS
 
ok habs schon fast, hoffe ich... :oops:

Kann das Projekt (dein Projekt, AlterMann) aber noch nicht kompillieren. Ich erhalte die Fehlermeldung:

[Pascal Fehler] frmMain.pas(151): E2003 Undefinierter Bezeichner: '__MIDL_0010'


//EDIT

Vielleicht liegst auch daran, dass ich zuerst nicht kompillieren konnte weil die Datei {$I WINDEFINES.INC} in Untit AdsErr fehlte...
ich habe die Datei einfach runtergeladen und im Suchverzeichnis des Projekts ergänzt.

JMD eine Idee


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:19 Uhr.
Seite 1 von 3  1 23      

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