AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen .NET-Sprachen C# [Erledigt] NetLocalGroupGetMembers auf x64 führt zu Programmabsturz
Thema durchsuchen
Ansicht
Themen-Optionen

[Erledigt] NetLocalGroupGetMembers auf x64 führt zu Programmabsturz

Ein Thema von leddl · begonnen am 17. Jun 2010 · letzter Beitrag vom 17. Jun 2010
Antwort Antwort
Benutzerbild von leddl
leddl

Registriert seit: 13. Okt 2003
Ort: Künzelsau
1.613 Beiträge
 
Delphi 2006 Professional
 
#1

[Erledigt] NetLocalGroupGetMembers auf x64 führt zu Programmabsturz

  Alt 17. Jun 2010, 12:32
Hallo zusammen,

Crosspost

wir versuchen hier zur Zeit, eine alte C++-DLL zu C# zu migrieren, die für den SQL-Server 2008 Stored Procedures bereitstellt. Diese Prozeduren werden genutzt, um Gruppen und Benutzer des Servers auszulesen. (Bevor entsprechende Hinweise kommen: Mir ist bewusst, dass man in C# die Gruppen auch anders auslesen kann, aufgrund der Verknüpfung mit dem SQL-Server scheinen wir aber auf die Verwendung der NetAPI32.dll festgelegt zu sein)

Teilweise klappt das ganz gut, so konnten wir schon den LogIn von Usern verifizieren oder auch alle Gruppen eines angegebenen Users auslesen. Vor ein Problem stellt uns jetzt allerdings das Auslesen aller User einer bestimmten Gruppe. Auf unserem Entwicklungsrechner bekommen wir das korrekte Ergebnis, sobald wir dann die Prozedur aber auf dem Server ausführen, führt das nicht nur zu einem Fehler, nein, der SQL-Server schmiert einfach jedes Mal unaufhaltbar ab. Selbst try...catch zeigt keinerlei Wirkung.

Zu Testzwecken haben wir anschließend den entsprechenden Code mal in eine Applikation (siehe Anhang) gepackt. Selbige liefert wieder auf dem Entwicklungsrechner das erwartete Ergebnis, auf dem Server allerdings stürzt das Programm jedes Mal ab, sobald man eine Gruppe eingibt, die tatsächlich existiert (und User besitzt). Unsere Vermutung ist nun, dass das wohl etwas mit dem Betriebssystem zu tun hat, denn der Entwicklungsrechner hat 32bit, unser neuer Server 64bit (Windows Server 2008). Auch ein Test bei mir daheim hat ergeben, dass die Testanwendung weder auf Windows 7 64bit noch unter Vista 64bit funktioniert. ("Anwendung wurde geschlossen" oder so ähnlich, ohne Angabe einer Fehlermeldung)

Erstmal hier der entsprechende Code. Dabei wurde einfach nur ein Button, eine Textbox und eine Listbox auf die Form gezogen. Die Textbox dient zur Eingabe der Gruppenname, die Listbox zur Ausgabe der gefundenen User. Button sollte klar sein
Code:
using System.Runtime.InteropServices;
//...
[DllImport("NetAPI32.dll", CharSet = CharSet.Unicode)]
        public extern static int NetLocalGroupGetMembers(
            [MarshalAs(UnmanagedType.LPWStr)] string servername,
            [MarshalAs(UnmanagedType.LPWStr)] string localgroupname,
            int level,
            out IntPtr bufptr,
            int prefmaxlen,
            out int entriesread,
            out int totalentries,
            ref int resume_handle);
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        internal struct LOCALGROUP_MEMBERS_INFO_1
        {
            public int lgrmi1_sid;
            public int lgrmi1_sidusage;
            public string lgrmi1_name;
        }
        [DllImport("Netapi32.dll", SetLastError = true)]
        static extern int NetApiBufferFree(IntPtr Buffer);
//...
private void button1_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            int EntriesRead = 0;
            int TotalEntries = 0;
            int Resume = 0;
            IntPtr bufPtr;
            IntPtr iter;
            NetLocalGroupGetMembers(null, textBox1.Text, 1, out bufPtr, -1, out EntriesRead, out TotalEntries, ref Resume);
            try
            {
                iter = bufPtr;
                for (int i = 0; i < EntriesRead; i++)
                {
                    LOCALGROUP_MEMBERS_INFO_1 lgi = new LOCALGROUP_MEMBERS_INFO_1();
                    lgi = (LOCALGROUP_MEMBERS_INFO_1)Marshal.PtrToStructure(iter, typeof(LOCALGROUP_MEMBERS_INFO_1));
                    iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(LOCALGROUP_MEMBERS_INFO_1)));

                    listBox1.Items.Add(lgi.lgrmi1_name);
                }
            }
            catch (Exception ex)
            {
                listBox1.Items.Add("/!\\ :: " + ex.ToString());
            }
        }
Soooo, was passiert hier? Wir rufen die Funktion NetLocalGroupGetMembers aus der NetAPI32.dll auf. Den entsprechenden Code findet man mehrfach online, und an die entsprechende Vorgehensweise haben wir uns im Großen und Ganzen auch gehalten. Wir rufen also die Funktion mit den entsprechenden Parametern auf und sollten anschließend im out-Parameter bufPtr die Daten zurückbekommen. Anschließend wird daraus dann mittels Marshall.PtrToStructure eine lesbare Struktur erstellt.
Unser Problem konnten wir nach einigen Versuchen dann genau auf diese Umwandlung eingrenzen:
Code:
lgi = (LOCALGROUP_MEMBERS_INFO_1)Marshal.PtrToStructure(iter, typeof(LOCALGROUP_MEMBERS_INFO_1));
Genau dabei fällt alles zusammen. Offensichtlich stimmt bei einem 64bit-Betriebssystem in dem Speicherbereich, auf den bufPtr zeigt, etwas nicht.
Seltsamerweise (keine Ahnung, ob das etwas zur Sache beiträgt, ich erwähne es aber trotzdem mal) wird beim Aufruf von NetLocalGroupGetMembers auch der Wert TotalEntries nur beim 32bit-System gesetzt. Dort steht dann z.B., dass insgesamt (TotalEntries) 12 Datensätze gefunden wurden, von denen 12 gelesen (EntriesRead) wurden. Auf der 64bit-Maschine wird uns aber ausgegeben, es wurden 12 Datensätze gelesen, obwohl keiner gefunden wurde (TotalEntries = 0)...

Wir stehen hier vor einem absoluten Rätsel... Wir haben erfolglos mehrere Varianten ausprobiert und auch Tante Google schweigt leider eisern zu dem Thema. Darum habe ich die Hoffnung, dass vielleicht hier jemand bereits ähnliches versucht hat und eventuell einen kleinen Workaround hat. Auf die Verwendung der hier verwendeten Strukturen sind wir wie gesagt aber wohl leider festgelegt.

Danke schonmal im Voraus,

Axel
Angehängte Dateien
Dateityp: zip TestApp.zip (4,3 KB, 5x aufgerufen)
Axel Sefranek
A programmer started to cuss, cause getting to sleep was a fuss.
As he lay there in bed, looping round in his head
was: while(!asleep()) ++sheep;

Geändert von leddl (17. Jun 2010 um 16:50 Uhr) Grund: Thema geklärt
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.609 Beiträge
 
#2

AW: NetLocalGroupGetMembers auf x64 führt zu Programmabsturz

  Alt 17. Jun 2010, 14:00
Einfach in den Projektoptionen auf dem Tab 'Build' das Platform Target von 'Any CPU' auf 'x86' stellen.

Das Problem ist, das eine .NET Assembly ohne spezielle Platform-Angabe auf x64 Systemen tatsächlich auf 64bit fertig-compiliert und dann als x64 Prozess ausgeführt wird. Eine 32bit-native DLL kann aber nicht in einen 64bittigen Prozess geladen werden.

Andersrum kann ein 32bittiger Prozess wie der SQL Server keine 64bittige Assembly laden.

Das führt zu den Abstürzen. Wenn die Assembly auf 32bit 'zurechtgestutzt' wird (durch angabe dieses Flags), ist alles auch auf 64bit Systemen nur 32 bit und es sollte so tun wie auf dem Entwicklungssystem.
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  Mit Zitat antworten Zitat
Benutzerbild von leddl
leddl

Registriert seit: 13. Okt 2003
Ort: Künzelsau
1.613 Beiträge
 
Delphi 2006 Professional
 
#3

AW: NetLocalGroupGetMembers auf x64 führt zu Programmabsturz

  Alt 17. Jun 2010, 16:49
Danke für die Antwort, aber das war es nicht.
Betriebssystem ist 64bit, SQL-Server ist 64bit und die NetAPI32.dll ist auch 64bit (Nicht vom Namen täuschen lassen ). Der Zugriff auf die DLL funktioniert ja außerdem bei drei anderen Funktionen tadellos, nur das Auslesen der GruppenMember führt zu dem Fehler.

Wir konnten uns jetzt allerdings doch auf eine andere Art behelfen. Ursprünglich dachten wir, wir könnten die DirectoryServices nicht benutzen, da sich diese im VS nicht referenzieren ließen. Nachdem wir die System.DirectoryServices.dll aber im SQL-Server als Assembly angelegt hatten, konnten wir dann auch im Visual Studio darauf zugreifen und somit die deutlich einfachere Syntax benutzen. Die liefert nun auch am Server die korrekten Ergebnisse.

Danke trotzdem!
Axel Sefranek
A programmer started to cuss, cause getting to sleep was a fuss.
As he lay there in bed, looping round in his head
was: while(!asleep()) ++sheep;
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:26 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