Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Containerinhalt auflisten ADSI (https://www.delphipraxis.net/154361-containerinhalt-auflisten-adsi.html)

cherry 8. Sep 2010 11:09

Containerinhalt auflisten ADSI
 
Hi there...
Ich hab in meinem Programm ein AD Browser...
nun wollte ich zusätzlich in der Detailtabelle die Spalte "Anzeigename" oder displayName, nun wenn ich jetzt auf eine OU klicke
passiert zwar was ich will, nur das Tempo ist inakzeptabel geworden. Die Funktion hat jetzt (je nach Inhalt) z.B. 5 statt 0.5 sec.

Delphi-Quellcode:
procedure TEADSObject.EnumObjectsOfContainer(ADSPath: string; CallbackFunction: TCallbackObjectEx);
var
  Enum: IEnumVariant;
  Container: IADSContainer;
  varObj: OleVariant;
  Obj: IADS;
  Temp: LongWord;
  displayName: string;
begin
  AccessObject(ADSPath, IID_IADSContainer, Container);
  Enum := Container._NewEnum as IEnumVariant;
  if Enum <> nil then
  begin
    while (Enum.Next(1,varObj, Temp) = S_OK) do
    begin
      Obj := IDispatch(varObj) as IADS;
      try displayName := Obj.Get('displayName'); except displayName := ''; end; // OHNE DIESE EINE ZEILE IST DIE FUNKTION 10x SCHNELLER!
      CallbackFunction(Obj.Name, obj.Class_, obj.ADsPath, displayName);
    end;
  end;
end;
Ich denke es hat allgemein was mit Obj.get() zu tun, das scheint wohl viel zu langsam zu sein...
stell dir vor ich möchte noch mehr attribute auslesen, dann kann ich mir ja dazu einen Kaffe kochen!!!

Weiss jemand wie ich schneller an die Attribute komme?

Danke schon ma.

Alter Mann 8. Sep 2010 21:39

AW: Containerinhalt auflisten ADSI
 
Hallo cherry,

eine direkte Antwort nicht, aber vielleicht hilft es dir ja weiter: es gibt (ich nenne es mal so)
Zwangs-, Geschützte- und Optionale-Container.
Der jeweilige Aufruf ist in der MSDN dokumentiert. Die dazugehörigen Attribute werden in einem
Rutsch geliefert, so das dein try except entfallen kann/könnte.

vg

Remko 9. Sep 2010 09:06

AW: Containerinhalt auflisten ADSI
 
I think the problem is that this attribute is empty for a lot of objects but you can verify this by using another attribute.

If you want to get results quickly it would be better to use IDirectorySearch since the interface you are using now is really meant for scripting languages and is inherently slow.

BTW: the offer that you can test the new Active Directory unit for Jwscl which nicely wraps AD in classes and makes it accessable the Delphi oop way.

cherry 9. Sep 2010 13:09

AW: Containerinhalt auflisten ADSI
 
Hallo Zusammen. Erstmal danke für die Antworten.
@Remko: Ich habe versucht es mit IDirectorySerch zu machen, aber da habe ich ein entscheidendes Problem:
Es scheint mir die Einstellung ADS_SEARCHPREF_SEARCH_SCOPE nicht korrekt zu setzten, ich erhalte somit viel zu viel ergebnisse.
Ich möchte die Einstellung auf ADS_SCOPE_ONELEVEL setzen damit ich nur Ergebnisse der OU erhalte aber das klappt nicht. Liegts an meinem Code`?

New AD Unit? - Welches Repository ?

Delphi-Quellcode:
procedure TEADSObject.EnumObjectsOfContainer(CallbackFunction: TCallbackResultArray; Attributes: string = 'Name;AdsPath;'; AdsPath: string = 'ROOTDSE');
var
  search: IDirectorySearch;
  ptrResult: ADS_SEARCH_HANDLE;
  opt: ads_searchpref_info;
  dwCount: DWORD;
  hr: HResult;
  col: ads_search_column;

  dwErr: DWord;
  szErr    : array[0..255] of WideChar;
  szName   : array[0..255] of WideChar;
  I: Integer;

  ArrResult: TStringArray2;
  ArrResCnt: Integer;
  AttrArray: array of PWideChar;
  Attribute: string;
  empty: Boolean;
begin

  // create an attributes array from the attributes passed by a delimitted string
  for I := 1 to Length(Attributes) do
  begin
    if Attributes[I] = ';' then
    begin
      SetLength(AttrArray, Length(AttrArray)+1);
      getmem(AttrArray[Length(AttrArray)-1], 256);
      StringToWideChar(Attribute, AttrArray[Length(AttrArray)-1], 256);
      Attribute := '';
    end
    else
      Attribute := Attribute + Attributes[I]
  end;

  // for faster search set a LDAPBeginingPath to execute the search within this container
  if AdsPath = 'ROOTDSE' then
    AdsPath := AdsMgr.ADSController.LDAPPATH;

  // get the search object
  if SUCCEEDED(AccessObject(AdsPath, IDirectorySearch, search)) then
  begin
    try
      // set parameters
      opt.dwSearchPref := ADS_SEARCHPREF_SEARCH_SCOPE;// OR ADS_SEARCHPREF_SORT_ON;
      opt.vValue.dwType := ADSTYPE_INTEGER;
      opt.vValue.__MIDL_0010.Integer := ADS_SCOPE_ONELEVEL; // <<---------------------------- irgendwie wird das nicht richtig gesetzt!?
      // setting search preferences
      if not SUCCEEDED(search.SetSearchPreference(opt, 1)) then
      begin
        ADsGetLastError(dwErr, @szErr[0], 254, @szName[0], 254);
        ShowMessage(WideCharToString(szErr));
        Exit;
      end;
      // prepare
      dwCount := Length(AttrArray);
      ArrResCnt := 1;
      // execute the search
      hr := search.ExecuteSearch('(objectCategory=*)', @AttrArray[0], dwCount, ptrResult);
      // handle the result if hr is S_OK
      if SUCCEEDED(hr) then
      begin
        hr := search.GetNextRow(ptrResult);
        while hr <> S_ADS_NOMORE_ROWS do
        begin

          // dim result array
          SetLength(ArrResult, ArrResCnt);
          empty := true;

          // for each attribute you want to get (defined in AttrArray)
          for I := 0 to dwCount -1 do
          begin

            // get column
            if Succeeded(search.GetColumn(ptrResult, AttrArray[I], col)) then
            begin
              if col.pADsValues <> nil then
              begin

                if I = 0 then
                begin
                  if ExtractContainerPath(col.pADsValues^.__MIDL_0010.BackLink.ObjectName) <> AdsPath then
                  begin
                    search.FreeColumn(col);
                    break;
                  end;
                end;

                // dim result array (2 dimensional string array)
                SetLength(ArrResult[ArrResCnt-1], I+1);
                // fill values into the result array
                ArrResult[ArrResCnt-1,I] := col.pADsValues^.__MIDL_0010.BackLink.ObjectName;
                empty := false;

              end;
              search.FreeColumn(col);
            end;

          end;
          hr := search.GetNextRow(ptrResult);

          // only redim the result array next time, if there was a value found
          // we dont want empty fields in the result array.
          if (not empty) then
          begin
            // A CALLBACK AFTER EVERY SUCCEEDED ROW
            CallBackFunction(ArrResult);
            Inc(ArrResCnt);
          end;

        end;
      end;
      //search.CloseSearchHandle(ptrResult);
    except
      //search._Release;
      on e: EOleException do
        AdsMgr.SetLastError(e.Message);
    end;
  end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:12 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