Érdekes jelenség: van egy kódrészletem, ami tökéletesen megy, ha Visual Studio 2005 alatt létrehozott projektbe teszem bele, ám elszáll, ha Visual Studio 2008 alól próbálom használni. A kód a Program Files mappába próbál írni, így valahogy:
string programFiles = Environment.GetFolderPath( Environment.SpecialFolder.ProgramFiles );
string subFolder = Path.Combine( programFiles, "MSDNKK teszt" );
Directory.CreateDirectory( subFolder );
Egyszerű .NET 2.0 System.IO, semmi extra. Kihasználom, hogy Vista alatt működik a mappa virtualizáció, tehát ha nincs is jogom írni a Program Files mappába, a Vista majd létrehozza ezen az útvonalon:
C:UsersbalassyAppDataLocalVirtualStoreProgram FilesMSDNKK teszt
Ez tökéletesen működik VS 2005 alól, ám VS 2008 alatt ugyanez a kód mintha kikerülné a mappa virtualizációt és jön az XP alatt megszokott kivétel:
System.UnauthorizedAccessException: Access to the path ‘C:Program FilesMSDNKK teszt’ is denied.
A megoldás a bin mappában lakik, még pedig alkalmazásnév.vshost.exe.manifest néven – a VS 2008 ugyanis létrehozza ezt a fájlt, a VS 2005 viszont nem. Ez van benne:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
A lényeg a requestedExecutionLevel, amit a Studio jó érzékkel asInvoker értékkel hoz létre – ez a javasolt. Ha így hagyjuk, azzal azt jelezzük az operációs rendszernek, hogy jól nevelt Windows alkalmazásról van szó, ami ugyanolyan access tokennel futhat, mint a szülő process. Már pedig egy jól nevelt alkalmazás nem irogat a Program Files mappába és egyéb közös területekre (pl. HKLM) sem, és ha ez így van, akkor a Windows szépen kikapcsolja a virtualizációt!
Nosza próbáljuk meg átállítani ezt az értéket! Választhatunk a lehetséges highestAvailable vagy requireAdministrator közül bármelyiket, virtualizációnk akkor sem lesz! Hiszen pont ez a lényeg, a helyi admin épp a Program Files mappába akar írni.
Ez a kapcsoló azért jó valamire:
Ahogy a pajzs ikon is jelzi, megkaphatjuk érte a consent vagy a credential promptot, attól függően, hogy rendszergazdák vagyunk vagy mezei felhasználók. Adminként pedig már nem lesz szükségünk a virtualizációra.
Már csak egy információval vagyok adós: hogyan lehet mindezt szabályozni Visual Studio 2008-ban. Természetesen a Project Properties ablakban:
Alapértelmezés szerint ez az opció Embed manifest with default settings értéken áll, ezért hozza létre a Studio a bin mapában a .manifest állományt. Ha ezt ki akarjuk kapcsolni és vissza akarunk állni a Visual Studio 2005 üzemmódra, akkor válasszuk a Create application without a manifest értéket és legalább legyen lelkiismeret furdalásunk, hogy miért nem írunk "jól nevelt" alkalmazást.
Helyette inkább másoljuk le a generált fájlt, nevezzük át mondjuk app.manifestre, vegyük fel a Solution Explorerbe, majd válasszuk ki a fenti ablakban. Így jól kézben tarthatjuk ezt a beállítást és ha valóban írni akarunk közös mappákba vagy registry kulcsokba, akkor rajzoltassuk oda azt a pajzsot, hadd lássa ország-világ, hogy ennek az alkalmazásnak admin jog kell!
A requestedExecutionLevel beállítással kapcsolatban bővebb információ az MSDN UAC példájában található, a cikkhez tartozó példakód pedig letölthető az MSDN Kompetencia Központ oldaláról.