![]() |
[Erledigt] NetLocalGroupGetMembers auf x64 führt zu Programmabsturz
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,
![]() 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:
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.
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()); } } Unser Problem konnten wir nach einigen Versuchen dann genau auf diese Umwandlung eingrenzen:
Code:
Genau dabei fällt alles zusammen. Offensichtlich stimmt bei einem 64bit-Betriebssystem in dem Speicherbereich, auf den bufPtr zeigt, etwas nicht.
lgi = (LOCALGROUP_MEMBERS_INFO_1)Marshal.PtrToStructure(iter, typeof(LOCALGROUP_MEMBERS_INFO_1));
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 |
AW: NetLocalGroupGetMembers auf x64 führt zu Programmabsturz
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. |
AW: NetLocalGroupGetMembers auf x64 führt zu Programmabsturz
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 :mrgreen:). 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! :thumb: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:19 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz