Nem először sikerül belefutnom az alábbi kivételbe, szinte mindig valamilyen egyedi telepítő futtatása közben:
“System.Security.Principal.IdentityNotMappedException: Nem lehet lefordítani néhány azonosítási hivatkozást, illetve egyet sem.”
Na kösz, és ez mit jelent?
Angolul egy kicsit közelebb juthatunk a megoldáshoz:
“Some or all identity references could not be translated.”
Már csak az a kérdés, hogy mi az az identity reference és mi az a translate. A problémát az eddigi esetekben mindig az jelentette, hogy a telepítő jogosultságot akart osztogatni egy mappán vagy registry kulcson, mégpedig egy konkrét felhasználó számára, tehát itt kell elkezdenünk keresgélni. A feladat valóban megoldható .NET-ben, a System.Security.Principal névteret használva, az NTAccount osztály segítségével meg tudok nevezni (reference) egy felhasználót (identity) és tudok neki jogot adni. A Windows hozzáférés szabályozási listáiban (Access Control List – ACL) az Access Control Entry-k mindig SID (Security IDentifier)-jogosultság párosokat tartalmaznak, tehát hiába adok meg egy felhasználó nevet, azt mindig SID-dé kell változtatni (translate), hogy tudjunk neki jogot adni. Szerencsére ezt a háttérben a .NET Framework osztályai megoldják helyettünk.
A fenti IdentityNotMappedException akkor keletkezik, amikor nem sikerült a névből SIDet gyártani, ez pedig tipikusan akkor fordul elő, amikor a “Rendszergazda” vagy a “Hálózatszolgáltatás” felhasználóra vagy éppen a “Rendszergazdák” csoportra hivatkozunk és a kódunkat angol operációs rendszeren futtatjuk, ahol nincs ilyen csoport. Vagy éppen fordítva, magyar Windowson keres a kódunk “Network Service” nevű felhasználót.
Ha a kódot nem mi írtuk, akkor a megoldás egy csoport létrehozása “Network Service” néven, amibe belepakoljuk a “Hálózatszolgáltatás” felhasználót és egy csapásra működni fog a kód.
Ha a kódot mi írtuk, akkor a megoldás az, hogy elszégyelljük magunkat, mert még nem hallottunk az ún. nevezett well-known SID-ekről vagy mert lusták voltunk használni őket. A standard felhasználóknak és csoportoknak a SID-jük is standard, nem csoda, hogy van rá enum a .NET Frameworkben, úgy hívják hogy WellKnownSidType. A használata pofonegyszerű, annyi a lényeg, hogy nem az NTAccount osztályt kell használni, hanem annak testvérét, a SecurityIdentifiert:
DirectoryInfo di = new DirectoryInfo( @"C:\Teszt" );
DirectorySecurity acl = di.GetAccessControl();
SecurityIdentifier sid = new SecurityIdentifier( WellKnownSidType.NetworkServiceSid, null );
FileSystemAccessRule ace = new FileSystemAccessRule( sid, FileSystemRights.Write, AccessControlType.Deny );
acl.AddAccessRule( ace );
di.SetAccessControl( acl );
Ez már nem fog olyan könnyen elhasalni.