Előzmény: telepítő alkalmazás jól működik angol Windowson, elszáll magyaron. Vajon mi lehet az oka? Némi búvárkodás után egyáltalán nem meglepő eredményre jutottam: a Felhasználók.
Ha jogosultságokat szeretnénk állítgatni egy mappán .NET-ből, akkor 2005 óta örülhetünk, mert a .NET 2.0 már támogatja hozzáférés szabályozási listák, azaz ACL-ek (Access Control List) kezelését. Rá is kattanhatunk rögtön a FileSystemAccessRule osztályra és nem lepődünk meg, hogy a konstruktor első paramétere egy SID, azaz security identifier. Nagyon szép, hogy a SID-ek leírására létezik egy SecurityIdentifier osztály a System.Security.Principal névtérben és milyen egyszerű a konstruktornak paraméterként megadni, hogy például a @"BUILTIN\Users" csoportra vagyunk kíváncsiak. Király, hogy van BUILTIN, mert így nem kell bedrótoznunk a gépnevet, ám miközben ennek örülünk, sikerült bedrótoznunk a Users csoport nevét. És hasonlóan lehet például az Administrator vagy a Network Service fiókról is szó. Mi ezekben a közös? Hogy más operációs rendszereken máshogy hívják őket, konkrétabban van Rendszergazda, Network Service és vannak Felhasználók is.
Végignézve a bevezetőben említett kódot, azért dobott exceptiont, mert a Users csoport nem létezik magyar Windowson, ott ugyanis Felhasználóknak hívják. Most akkor drótozzuk be az összes lehetséges értéket?
A megoldás ennél azért szebb, köszönhetően annak, hogy bármennyire is azt szoktuk mondogatni, hogy a SID egyedi, valójában nem az. A minden gépen létező csoportoknak és felhasználóknak ún. well-known SID-jük van, azaz előre lehet tudni őket. A jó hír az, hogy létezik egy CreateWellKnownSid nevű Win32 API függvény, ami képes visszaadni ezeket az ismert SID-eket és hogy még szebb legyen a kép, ezt meg lehet hívni P/Invoke-kal .NET-ből, sőt mi több, a SecurityIdentifier osztály helyből képes erre, ha a WellKnownSidType paraméterezésű konstruktorát használjuk.
Ezek alapján tehát például így hozhatunk létre mappát úgy, hogy a Felhasználók csoportnak biztos Full Control joga legyen rajta:
Directory.CreateDirectory( path );
DirectoryInfo dirInfo = new DirectoryInfo( path );
// @"BUILTIN\Users"
SecurityIdentifier sid = new SecurityIdentifier( WellKnownSidType.BuiltinUsersSid, null );
FileSystemAccessRule ace = new FileSystemAccessRule( sid, FileSystemRights.FullControl, AccessControlType.Allow );
DirectorySecurity acl = dirInfo.GetAccessControl();
acl.AddAccessRule( ace );
dirInfo.SetAccessControl( acl );