A példában a Form első ComboBox kontroljában jelennek meg a számítógép felhasználói, a második lista a számítógép csoportjait tartalmazza. Amennyiben a listából kiválasztott felhasználót jelszó védi, akkor a régi és az új jelszó megadásával módosíthatja azt. Amennyiben nem, akkor a régi jelszó mezőjét üresen hagyva, és az új jelszó mezőt kitöltve jelszót adhat a felhasználónak.
A példa projektjében a NetworkClass.cs állományban létrehozott NetworkClass osztályban hoztuk létre az API függvényeket meghívó saját metódusokat.
A két lista feltöltéséhez szükség van két struktúra-deklarációra, melyek a kigyűjtött objektumok (felhasználók, és csoportok) neveit tartalmazzák. Ezek közül a USER_INFO_0 struktúra tartalmazza a felhasználók, míg a GROUP_INFO_0 struktúra a csoportok neveit.
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct USER_INFO_0
{
public String Username;
}
Látható, hogy az LPWSTR nem-menedzselt típust egyszerűen String típusú változóval helyettesítjük a menedzselt kódban. Így járunk el a GROUP_INFO_0 struktúrában is.
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct GROUP_INFO_0
{
public String Groupname;
}
A felhasználók neveinek kigyűjtését a NetUserEnum, míg a csoportok neveinek kigyűjtését a NetGroupEnum API függvény végzi el. Ezek meghívását a GetUserNames, illetve GetGroupNames metódusba ágyaztuk, melyek közül most az utóbbit mutatjuk be.
string[] groups = null;
int entries;
int fullentries;
int r;
IntPtr bufPtr;
A szükséges paraméterek deklarálása után meghívjuk a függvényt, melynek első paramétere tartalmazza a számítógép nevét, melynek felhasználó csoportjaira kíváncsiak vagyunk. Ez példánkban NULL, hiszen a lekérdezést a programot futtató számítógépre korlátozzuk.
A második paraméterben jelezzük, hogy milyen szintű információra van szükségünk. Ez most nulla, hiszen a legalacsonyabb szintű, csak a neveket tartalmazó információt kérjük, a GROUP_INFO_0 struktúrában. A harmadik paraméter tartalmazza a mutatót a struktúrára, melyet majd feldolgozunk.
A negyedik paraméterben adjuk meg (-1 értékkel), hogy mekkora adatmennyiség várhat. A -1 a legnagyobb értéket veszi alapul.
Az ötödik paraméterben kapjuk meg a bejegyzések számát.
NetGroupEnum(null, 0, out bufPtr, -1, out entries, out fullentries, out r);
Amennyiben nem nulla a bejegyzések száma, akkor egy, a fent deklarált struktúrákat tartalmazó tömbbe gyűjtjük az információkat.
if (entries > 0)
{
GROUP_INFO_0[] localgroups = new GROUP_INFO_0[entries];
groups = new string[entries];
for(int i=0;i<entries;i++)
{
localgroups[i] = GROUP_INFO_0)Marshal.PtrToStructure(bufPtr, typeof(GROUP_INFO_0));
bufPtr = (IntPtr)((int)bufPtr + Marshal.SizeOf(typeof(GROUP_INFO_0)));
groups[i] = localgroups[i].Groupname;
}
A művelet végén a NetApiBufferFree metódussal fel kell szabadítani a bufPtr mutató által lefoglalt memóriaterületet, a memóriaszivárgás elkerülése végett (memory leak).
NetApiBufferFree(bufPtr);
}
A felhasználó jelszavának módosításához, illetve új jelszó létrehozásához a NetUserChangePassword API meghívására van szükségünk. Ennek deklarációja a következő:
[DllImport("Netapi32.dll")]
public extern static int NetUserChangePassword([MarshalAs(UnmanagedType.LPWStr)] string domainname,[MarshalAs(UnmanagedType.LPWStr)] string username,[MarshalAs(UnmanagedType.LPWStr)] string oldpassword,[MarshalAs(UnmanagedType.LPWStr)] string newpassword);
A függvény első paramétere a számítógépnév, második paramétere a felhasználónév. Az utolsó két paraméterben pedig a régi és az új jelszavakat kell specifikálni.
A meghívást a ChangePassword metódusba ágyaztuk, egyszerűen karakterláncokat adva át az API függvénynek.
public bool ChangePassword(string servername, string username, string oldpass, string newpass)
{
... NetUserChangePassword(servername,username,oldpass,newpass)
...
}
A számítógép nevét itt is NULL értékkel adjuk meg.