Delphi-PRAXiS
Seite 1 von 9  1 23     Letzte » 

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Zugriffsverletzung ADSI, so was komisches hab ich noch nie.. (https://www.delphipraxis.net/146499-zugriffsverletzung-adsi-so-komisches-hab-ich-noch-nie.html)

cherry 21. Jan 2010 06:37


Zugriffsverletzung ADSI, so was komisches hab ich noch nie..
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Leute

Langsam aber sicher verzweifle ich an folgender Problematik:

- Ich arbeite an einem Benutzerfreundlichen AD Programm, Benutzer erstellen, ändern löschen usw.
- Ich verwende folgene Units: ADsTLB, adshlp, AdsErr (Im Download enthalten)

Zum Problem...

Ich arbeite in diesem Zusammenhang an einer Unit, die den Zugriff aufs AD sehr simpel gestalten soll. Nun kommt es sehr oft zu "unerklärlichen" Zugriffsverletzungen.
Schauen wir uns folgendes Beispiel an:

Delphi-Quellcode:

// Endet in Zugriffsverletzung
procedure TForm1.Button1Click(Sender: TObject);
begin
  ADsMgr.ADSGroups.EnumAllGroups(CBF);
  Caption := 'Zugriffsverletzung'; // <-- Zugriffsverletzung immer bei der darauf folgenden Zeile, egal was hier steht.
end;

// Endet NICHT in Zugriffsverletung
procedure TForm1.Button2Click(Sender: TObject);
begin
  DUMMY;
  Caption := 'KEINE Zugriffsverletzung';
end;

// Dummy function ermöglicht das Ausführen der Funktion ohne Zugriffsverletzung
procedure TForm1.DUMMY;
begin
  ADsMgr.ADSGroups.EnumAllGroups(CBF);
end;
Ach ja, wenn die Exe nicht in der Entwicklungsumgebung gestartet wird, erscheint nicht mal eine Fehlermeldung, das Programm beentet einfach automatisch!
Ihr könnt euch das Beispielprogramm gerne mal anschauen. Ich versteh die Welt nicht mehr :stupid:

Bbommel 21. Jan 2010 08:32

Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
 
Hallo,

ich habe mir das Projekt jetzt noch nicht runtergeladen, sondern glaube einfach mal deiner Fehlerbeschreibung. :) Ähnliche Effekte habe ich auch ein bis zwei Mal im Jahr - normalerweise hat das dann mit der Stelle selbst, an der die AV auftritt, eher wenig zu tun, sondern liegt daran, dass ich mir irgendwie den Speicher zerschossen habe. Beliebte Ursachen dafür sind Zugriffe auf Objekte, die ich schon freigegeben hatte, oder falsche Typecasts, so dass ich auf Eigenschaften eines Objekts zugreifen möchte, die es gar nicht hat.

Dass sich das Programm dann mit und ohne Debugger völlig anders verhalten hat, hatte ich dann auch gerne mal - klar, dann "liegt" ja sicherlich auch so einiges anders im Speicher und dadurch taucht dann die AV nicht auf.

Viel Spaß beim Suchen. :)

Bis denn
Bommel

Sunlight7 21. Jan 2010 08:45

Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
 
Sowas passiert auch gerne, wenn man über die Länge einens Speicherbereichs hinausschreibt.

nahpets 21. Jan 2010 08:53

Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
 
Hallo,

kann mich schwach ein ein ähnliches Problem in diesem Umfeld erinnern. Soweit ich das in Erinnerung behalten habe, ließ sich das Problem "simpel" lösen. Zuweisungen nur an lokale Variabeln machen und diese dann an die globeln Variablen... zuweisen. In Deinem Beispiel könnte dann eventuell unterumständen vielleicht ... folgendes helfen:

Delphi-Quellcode:
// Endet hoffentlich nicht mehr in Zugriffsverletzung
procedure TForm1.Button1Click(Sender: TObject);
Var
          sCaption : String;
begin
  ADsMgr.ADSGroups.EnumAllGroups(CBF);
  sCaption := 'jetzt keine Zugriffsverletzung mehr'
  Caption := sCaption; // <-- Zugriffsverletzung nicht mehr immer bei der darauf folgenden Zeile, egal was hier steht.
end;
Bin mir aber absolut nicht sicher, ob ich hier jetzt eventuell doch irgendwas durcheinander werfe. Aber einen Versuch ist es ja vielleicht doch wert ;-)

Der Fehler ist jedenfalls in den Innereien dieses Befehls zu suchen:
Delphi-Quellcode:
ADsMgr.ADSGroups.EnumAllGroups(CBF);
Wo ist CBF definiert, eventuell hilft hier eine Veränderung von global nach lokal oder rein in die Klasse oder raus aus der Klasse.

hoika 21. Jan 2010 10:05

Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
 
Hallo,

TStringArray2 -> array of array of String uiui ;)

Hast du deinen CBF-Code mal ausgeklammert ?
er sieht aber eigentlich OK aus.

Könnte es sein, dass man hier WideString / AnsiString nehmen muss
Du hast ja D2009, viell. hatte der Autor eine kleinere Delphi-Version. ?


Das mit dem Abstürzen bekommst du übrigens mit try/except hin.


Delphi-Quellcode:
procedure TForm1.CBF(data: TStringArray2);
var
  X,Y : Integer;
  txt : String;
  txt1 : String;
begin
  for X := Low(data) to High(data) do
  begin
    txt := '';
    for Y := Low(data[X]) to High(data[X]) do
    begin
      txt1:= data[X,Y];
      txt := txt + ' > ' + txt1;
    end;
    ListBox1.Items.Add(txt);
  end;
end;
Das läßt sich besser Debuggen.
Ev. hilft auch ein SetLength (auf txt und txt1).
Intern (TEADSObject.DirectorySearch) wird ja auch mit SetLength gearbeitet.



Heiko

cherry 21. Jan 2010 10:43

Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
 
Zitat:

Zitat von nahpets
Hallo, In Deinem Beispiel könnte dann eventuell unterumständen vielleicht ... folgendes helfen... ...Aber einen Versuch ist es ja vielleicht doch wert ;-) ...

> Dies wäre ja dann auch keine Lösung sondern nur ein anderes Workaraound als ich "vorgeschlagen" habe. Habs troztdem mal ausprobiert. Klappt nicht, wenn ich es so mache wie du vorgeschlagen hast, passiert die Zugriffsverletzung einfach bei dieser Zeile: " sCaption := 'jetzt keine Zugriffsverletzung mehr' "

Zitat:

Zitat von nahpets
Der Fehler ist jedenfalls in den Innereien dieses Befehls zu suchen:
Delphi-Quellcode:
ADsMgr.ADSGroups.EnumAllGroups(CBF);
Wo ist CBF definiert, eventuell hilft hier eine Veränderung von global nach lokal oder rein in die Klasse oder raus aus der Klasse.

> Ich vermute, dass der Fehler in den verwendeten Übersetzungsunits liegt... in ADsTLB, adshlp oder AdsErr...
Die Procedure ADsMgr.ADSGroups.EnumAllGroups ist bestandteil von meiner, eben angesprochenen, Unit die den Zugriff aufs AD sehr simpel gestalten soll. (Name der Unit EExtemporanousMumblings)
Ich verwende in der ganzen Unit nur eine einzige Globale Variable und das ist die Klasse selbst: ADSManager: TADSManager; damit ich die Unit einfach einbinden und loslegen kann und nicht noch Instanzieren muss!

Zitat:

Zitat von Sunklight7
Sowas passiert auch gerne, wenn man über die Länge einens Speicherbereichs hinausschreibt.

> Dann würde mein Workaround aber nicht funktionieren. An dem liegts aus meiner Sicht wohl kaum.

Zitat:

Zitat von hoika
Hallo,
TStringArray2 -> array of array of String uiui ;)

könnte man das auch anders lösen, ich denke wenn ich sowas als Parameter habe muss ich zwingend einen Typ davon machen?!

Zitat:

Zitat von hoika
Hast du deinen CBF-Code mal ausgeklammert ?

Soeben, ja. Die Zugriffsverletzung bleibt.

Zitat:

Zitat von hoika
Könnte es sein, dass man hier WideString / AnsiString nehmen muss
Du hast ja D2009, viell. hatte der Autor eine kleinere Delphi-Version. ?

Der Autor von was? EExtemporanousMumblings ist von mir. > Die fehler kommen entweder von dort, oder was ich vermute: Sie liegen in einer der Units: ADsTLB, adshlp, AdsErr...
Kennt jemand die Units: ADsTLB, adshlp, AdsErr ich find keine neueren Versionen.

Zitat:

Zitat von hoika
Das mit dem Abstürzen bekommst du übrigens mit try/except hin.

Eben nicht: Das ist ja das verdammt komische!!!! Wenn ich ein try except mache, schliesst das Programm einfach ohne meldung!!!!

nahpets 21. Jan 2010 11:19

Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
 
Hallo,
Zitat:

Zitat von cherry
Der Autor von was? EExtemporanousMumblings ist von mir. > Die fehler kommen entweder von dort, oder was ich vermute: Sie liegen in einer der Units: ADsTLB, adshlp, AdsErr...
Kennt jemand die Units: ADsTLB, adshlp, AdsErr ich find keine neueren Versionen.

Zitat:

Zitat von hoika
Das mit dem Abstürzen bekommst du übrigens mit try/except hin.

Eben nicht: Das ist ja das verdammt komische!!!! Wenn ich ein try except mache, schliesst das Programm einfach ohne meldung!!!!

Den zuletzt genannten Effekt hatte ich auch, eigene Fehlerbehandlung zwecklos, Deine Fehlerortvermutung stimmt mit meinen Erfahrungen überein. Leider komme ich nicht mehr an den alten Quelltext, alter Arbeitgeber, alte Arbeit. Andernfalls könnte ich nachschauen, wie ich seinerzeit (per Workaround) um das Problem herumgekommen bin.

Hast Du sCaption mal als globale Variabel deklariert? Kann mich leider nicht mehr erinnern, was ich seinerzeit wo und wie deklariert hatte, es war aber ziemlich abstruse und ein uneleganter Workaround.

Bbommel 21. Jan 2010 12:50

Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
 
Zitat:

Zitat von cherry
Ich vermute, dass der Fehler in den verwendeten Übersetzungsunits liegt... in ADsTLB, adshlp oder AdsErr...

Zumindest die ADsTLB könntest du ja selber mal neu machen. Das ist ja nur ein Wrapper für die Datei activeds.tlb aus dem Windows-Systemverzeichnis. Vielleicht würde es ja helfen, diese Bibliothek mal unter D2009 selbst neu zu importieren. Evtl. läuft dann ja alles besser oder du stößt in den Units adshlp und adserr, die ja letztlich auch nur ADsTLB zu verwenden scheinen, eher auf den Kern des Problems.

Ich habe mal versucht, das Problem hier nachzuvollziehen, bin allerdings nicht in einer AD-Umgebung, insofern macht das Programm bei mir auch nur eingeschränkt Sinn. Es meldet aber immerhin, dass es kein ActiveDirectory finden konnte (das fängst du übrigens nicht ab, wodurch dann nachher eine OleException geworfen wird, weil du immer davon ausgehst, dass etwas gefunden wurde) und dann ist alles gut. Ich habe das OnClick-Event mal zu
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  try
     ADsMgr.ADSGroups.EnumAllGroups(CBF);
  finally
     Caption := 'Zugriffsverletzung';
  end;
end;
umgebaut. Eine AV gibt es bei mir nicht mehr. Das nur noch mal als bestätigender Hinweis, dass das Problem wahrscheinlich in den genutzten Units liegt.

cherry 21. Jan 2010 14:23

Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
 
Huuuuch... Ich glaub ich hab da eine Spur. Die ADsTLB wurde im Jahre 2007 generiert. Könnte es wohl daran liegen?
Ich hab sie mal neu wrappen lassen...

Nun habe ich aber bei meiner "DirectorySearch" Funktion probleme, ich krieg sie nicht mehr zum laufen:

Folgende deklarationen haben geändert:
von:
Delphi-Quellcode:
function GetNextRow(hSearchResult: THandle): HResult; stdcall;
function ExecuteSearch(pszSearchFilter: PWideChar; pAttributeNames: PWideChar;
                           dwNumberAttributes: LongWord; out phSearchResult: THandle): HResult; stdcall;
function GetColumn(hSearchResult: THandle; szColumnName: PWideChar;
                       out pSearchColumn: ads_search_column): HResult; stdcall;
function CloseSearchHandle(var hSearchResult: THandle): HResult; stdcall;
auf:
Delphi-Quellcode:
function GetNextRow(var hSearchResult: Pointer): HResult; stdcall;
function ExecuteSearch(pszSearchFilter: PWideChar; var pAttributeNames: PWideChar;
                           dwNumberAttributes: LongWord; out phSearchResult: Pointer): HResult; stdcall;
function GetColumn(var hSearchResult: Pointer; szColumnName: PWideChar;
                       out pSearchColumn: ads_search_column): HResult; stdcall;
function CloseSearchHandle(var hSearchResult: Pointer): HResult; stdcall;
Es reicht aber dann nicht ptrResult auf Pointer zu ändern. Es gibt wieder eine Zugriffsverletzung (Stelle ist markiert). Jedoch stürzt das Programm danach nicht ab,
ist immerhin schon etwas. Kann mir jemand helfen?

Delphi-Quellcode:
procedure TEADSObject.DirectorySearch(searchfilter: string; CallBackFunction: TCallBackResultArray; Attributes: string = 'Name;AdsPath;'; LDAPBeginingPath: string = 'ROOTDSE');
var
  search: IDirectorySearch;
  ptrResult: POINTER;
  opt: ads_searchpref_info;
  dwCount: DWORD;
  hr: HResult;
  col: ads_search_column;

  dwErr: DWord;
  szErr    : array[0..255] of Char;
  szName   : array[0..255] of Char;
  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 LDAPBeginingPath = 'ROOTDSE' then
    LDAPBeginingPath := AdsMgr.ADSController.LDAPPATH;

  // get the search object
  if SUCCEEDED(AdsGetObject(LDAPBeginingPath, 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_SUBTREE;
      // 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(StringToOleStr(searchfilter), AttrArray[0], dwCount, ptrResult);
      // handle the result if hr is S_OK
      if SUCCEEDED(hr) then
      begin
        // get first row
        hr := search.GetNextRow(ptrResult); // <------------ Dies löst den Fehler aus !!!!
        // repeat until no more rows
        while (hr <> S_ADS_NOMORE_ROWS) do
        begin

          // redim 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
                // redim 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
            Inc(ArrResCnt);

        end;
      end;
      search.CloseSearchHandle(ptrResult);
    finally
      search._Release;
    end;
  end;
  if Length(ArrResult) > 0 then
    CallBackFunction(ArrResult);
end;

cherry 21. Jan 2010 15:21

Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
 
Das deklarationsproblem hatten wir schon mal hier

Habe nun die Pointer in THandles geändert, kompilieren geht, nur der Fehler tritt am selben Ort auf.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:39 Uhr.
Seite 1 von 9  1 23     Letzte » 

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