1. How to check if the current process is running as administrator?
2. How to know if the primary access token of the current process belongs to user account that is a member of the local Administrators group, even if it currently is not elevated?
3. How to check if the current process is elevated? The elevation information is available to only Windows Vista and newer operating systems because there was no UAC and “elevation” before Windows Vista.
4. How to get the integrity level of the current process (System/High/Medium/Low/Unknown)? The integrity level information is available to only Windows Vista and newer operating systems because there was no UAC and “integrity level” before Windows Vista.
5. How to show an UAC shield icon on the UI for tasks that requires elevation?
6. How to self-elevate the current process?
7. How to automatically elevate the process when it's started up?
We provide code samples to demonstrate the above how-to scenarios in three programming languages (native VC++, VC#, VB.NET) to meet the needs of different developers.
Language
Sample
VC++
CppUACSelfElevation
VC#
CSUACSelfElevation
VB.NET
VBUACSelfElevation
The code samples are part of MicrosoftAll-In-One Code Framework, which is a centralized code sample solution from Microsoft.You can download the code from the project’s Download page:http://1code.codeplex.com/releases/.
演示 This is a quick demo of the attached UAC samples.
Step1. After you successfully build the sample project in Visual Studio 2008, you will get an application depending on the programming language that you are using: CppUACSelfElevation.exe / CSUACSelfElevation.exe / VBUACSelfElevation.exe.
Step2. Run the application as a protected administrator on a Windows Vista or Windows 7 system with UAC fully enabled. The application should display the following content on the main dialog. There is a UAC shield icon on the Self-elevate button.
Step3. Click on the Self-elevate button. You will see a Consent UI.
Step4. Click Yes to approve the elevation. The original application will then be started and display the following content on the main dialog.
The Self-elevate button on the dialog does not have the UAC shield icon this time. That is, the application is running as elevated administrator. The elevation succeeds. If you click on the Self-elevate button again, the application will tell you that it is running as administrator.
Step5. Click OK to close the application.
代码 The code introduced in this section is for VC# developers only. You can find the VC++ and VB.NET implementations in the CppUACSelfElevation and VBUACSelfElevation sample packages.
1. How to check if the current process is running as administrator?
///<summary>
///Thefunctioncheckswhetherthecurrentprocessisrunasadministrator.
///Inotherwords,itdictateswhethertheprimaryaccesstokenofthe
///processbelongstouseraccountthatisamemberofthelocal
///Administratorsgroupanditiselevated.
///</summary>
///<returns>
///Returnstrueiftheprimaryaccesstokenoftheprocessbelongstouser
///accountthatisamemberofthelocalAdministratorsgroupanditis
///elevated.Returnsfalseifthetokendoesnot.
///</returns>
internalboolIsRunAsAdmin()
{
WindowsIdentityid=WindowsIdentity.GetCurrent();
WindowsPrincipalprincipal=newWindowsPrincipal(id);
returnprincipal.IsInRole(WindowsBuiltInRole.Administrator);
}
2. How to know if the primary access token of the current process belongs to user account that is a member of the local Administrators group, even if it currently is not elevated?
///<summary>
///Thefunctioncheckswhethertheprimaryaccesstokenoftheprocessbelongs
///touseraccountthatisamemberofthelocalAdministratorsgroup,evenif
///itcurrentlyisnotelevated.
///</summary>
///<returns>
///Returnstrueiftheprimaryaccesstokenoftheprocessbelongstouser
///accountthatisamemberofthelocalAdministratorsgroup.Returnsfalse
///ifthetokendoesnot.
///</returns>
///<exceptioncref="System.ComponentModel.Win32Exception">
///WhenanynativeWindowsAPIcallfails,thefunctionthrowsaWin32Exception
///withthelasterrorcode.
///</exception>
internalboolIsUserInAdminGroup()
{
boolfInAdminGroup=false;
SafeTokenHandlehToken=null;
SafeTokenHandlehTokenToCheck=null;
IntPtrpElevationType=IntPtr.Zero;
IntPtrpLinkedToken=IntPtr.Zero;
intcbSize=0;
try
{
//Opentheaccesstokenofthecurrentprocessforqueryandduplicate.
if(!NativeMethod.OpenProcessToken(Process.GetCurrentProcess().Handle,
NativeMethod.TOKEN_QUERY|NativeMethod.TOKEN_DUPLICATE,outhToken))
{
thrownewWin32Exception(Marshal.GetLastWin32Error());
}
//DeterminewhethersystemisrunningWindowsVistaorlateroperating
//systems(majorversion>=6)becausetheysupportlinkedtokens,but
//previousversions(majorversion<6)donot.
if(Environment.OSVersion.Version.Major>=6)
{
//RunningWindowsVistaorlater(majorversion>=6).
//Determinetokentype:limited,elevated,ordefault.
//Allocateabufferfortheelevationtypeinformation.
cbSize=sizeof(TOKEN_ELEVATION_TYPE);
pElevationType=Marshal.AllocHGlobal(cbSize);
if(pElevationType==IntPtr.Zero)
{
thrownewWin32Exception(Marshal.GetLastWin32Error());
}
//Retrievetokenelevationtypeinformation.
if(!NativeMethod.GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenElevationType,pElevationType,
cbSize,outcbSize))
{
thrownewWin32Exception(Marshal.GetLastWin32Error());
}
//MarshaltheTOKEN_ELEVATION_TYPEenumfromnativeto.NET.
TOKEN_ELEVATION_TYPEelevType=(TOKEN_ELEVATION_TYPE)
Marshal.ReadInt32(pElevationType);
//Iflimited,getthelinkedelevatedtokenforfurthercheck.
if(elevType==TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited)
{
//Allocateabufferforthelinkedtoken.
cbSize=IntPtr.Size;
pLinkedToken=Marshal.AllocHGlobal(cbSize);
if(pLinkedToken==IntPtr.Zero)
{
thrownewWin32Exception(Marshal.GetLastWin32Error());
}
//Getthelinkedtoken.
if(!NativeMethod.GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenLinkedToken,pLinkedToken,
cbSize,outcbSize))
{
thrownewWin32Exception(Marshal.GetLastWin32Error());
}
//Marshalthelinkedtokenvaluefromnativeto.NET.
IntPtrhLinkedToken=Marshal.ReadIntPtr(pLinkedToken);
hTokenToCheck=newSafeTokenHandle(hLinkedToken);
}
}
//CheckTokenMembershiprequiresanimpersonationtoken.Ifwejustgot
//alinkedtoken,italreadyisanimpersonationtoken.Ifwedidnot
//getalinkedtoken,duplicatetheoriginalintoanimpersonation
//tokenforCheckTokenMembership.
if(hTokenToCheck==null)
{
if(!NativeMethod.DuplicateToken(hToken,
SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
outhTokenToCheck))
{
thrownewWin32Exception(Marshal.GetLastWin32Error());
}
}
//CheckifthetokentobecheckedcontainsadminSID.
WindowsIdentityid=newWindowsIdentity(hTokenToCheck.DangerousGetHandle());
WindowsPrincipalprincipal=newWindowsPrincipal(id);
fInAdminGroup=principal.IsInRole(WindowsBuiltInRole.Administrator);
}
finally
{
//Centralizedcleanupforallallocatedresources.
if(hToken!=null)
{
hToken.Close();
hToken=null;
}
if(hTokenToCheck!=null)
{
hTokenToCheck.Close();
hTokenToCheck=null;
}
if(pElevationType!=IntPtr.Zero)
{
Marshal.FreeHGlobal(pElevationType);
pElevationType=IntPtr.Zero;
}
if(pLinkedToken!=IntPtr.Zero)
{
Marshal.FreeHGlobal(pLinkedToken);
pLinkedToken=IntPtr.Zero;
}
}
returnfInAdminGroup;
}
3. How to check if the current process is elevated? The elevation information is available to only Windows Vista and newer operating systems because there was no UAC and “elevation” before Windows Vista.
///<summary>
///Thefunctiongetstheelevationinformationofthecurrentprocess.It
///dictateswhethertheprocessiselevatedornot.Tokenelevationisonly
///availableonWindowsVistaandneweroperatingsystems,thus
///IsProcessElevatedthrowsaC++exceptionifitiscalledonsystemsprior
///toWindowsVista.Itisnotappropriatetousethisfunctiontodetermine
///whetheraprocessisrunasadministartor.
///</summary>
///<returns>
///Returnstrueiftheprocessiselevated.Returnsfalseifitisnot.
///</returns>
///<exceptioncref="System.ComponentModel.Win32Exception">
///WhenanynativeWindowsAPIcallfails,thefunctionthrowsaWin32Exception
///withthelasterrorcode.
///</exception>
///<remarks>
///TOKEN_INFORMATION_CLASSprovidesTokenElevationTypetochecktheelevation
///type(TokenElevationTypeDefault/TokenElevationTypeLimited/
///TokenElevationTypeFull)oftheprocess.ItisdifferentfromTokenElevation
///inthat,whenUACisturnedoff,elevationtypealwaysreturns
///TokenElevationTypeDefaulteventhoughtheprocessiselevated(Integrity
///Level==High).Inotherwords,itisnotsafetosayiftheprocessis
///elevatedbasedonelevationtype.Instead,weshoulduseTokenElevation.
///</remarks>
internalboolIsProcessElevated()
{
boolfIsElevated=false;
SafeTokenHandlehToken=null;
intcbTokenElevation=0;
IntPtrpTokenElevation=IntPtr.Zero;
try
{
//OpentheaccesstokenofthecurrentprocesswithTOKEN_QUERY.
if(!NativeMethod.OpenProcessToken(Process.GetCurrentProcess().Handle,
NativeMethod.TOKEN_QUERY,outhToken))
{
thrownewWin32Exception(Marshal.GetLastWin32Error());
}
//Allocateabufferfortheelevationinformation.
cbTokenElevation=Marshal.SizeOf(typeof(TOKEN_ELEVATION));
pTokenElevation=Marshal.AllocHGlobal(cbTokenElevation);
if(pTokenElevation==IntPtr.Zero)
{
thrownewWin32Exception(Marshal.GetLastWin32Error());
}
//Retrievetokenelevationinformation.
if(!NativeMethod.GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenElevation,pTokenElevation,
cbTokenElevation,outcbTokenElevation))
{
//WhentheprocessisrunonoperatingsystemspriortoWindows
//Vista,GetTokenInformationreturnsfalsewiththeerrorcode
//ERROR_INVALID_PARAMETERbecauseTokenElevationisnotsupported
//onthoseoperatingsystems.
thrownewWin32Exception(Marshal.GetLastWin32Error());
}
//MarshaltheTOKEN_ELEVATIONstructfromnativeto.NETobject.
TOKEN_ELEVATIONelevation=(TOKEN_ELEVATION)Marshal.PtrToStructure(
pTokenElevation,typeof(TOKEN_ELEVATION));
//TOKEN_ELEVATION.TokenIsElevatedisanon-zerovalueifthetoken
//haselevatedprivileges;otherwise,azerovalue.
fIsElevated=(elevation.TokenIsElevated!=0);
}
finally
{
//Centralizedcleanupforallallocatedresources.
if(hToken!=null)
{
hToken.Close();
hToken=null;
}
if(pTokenElevation!=IntPtr.Zero)
{
Marshal.FreeHGlobal(pTokenElevation);
pTokenElevation=IntPtr.Zero;
cbTokenElevation=0;

}
}
returnfIsElevated;
}
4. How to get the integrity level of the current process (System/High/Medium/Low/Unknown)? The integrity level information is available to only Windows Vista and newer operating systems because there was no UAC and “integrity level” before Windows Vista.
///<summary>
///Thefunctiongetstheintegritylevelofthecurrentprocess.Integrity
///levelisonlyavailableonWindowsVistaandneweroperatingsystems,thus
///GetProcessIntegrityLevelthrowsaC++exceptionifitiscalledonsystems
///priortoWindowsVista.
///</summary>
///<returns>
///Returnstheintegritylevelofthecurrentprocess.Itisusuallyoneof
///thesevalues:
///
///SECURITY_MANDATORY_UNTRUSTED_RID-meansuntrustedlevel.Itisused
///byprocessesstartedbytheAnonymousgroup.Blocksmostwriteaccess.
///(SID:S-1-16-0x0)
///
///SECURITY_MANDATORY_LOW_RID-meanslowintegritylevel.Itisusedby
///ProtectedModeInternetExplorer.Blockswriteacesstomostobjects
///(suchasfilesandregistrykeys)onthesystem.(SID:S-1-16-0x1000)
///
///SECURITY_MANDATORY_MEDIUM_RID-meansmediumintegritylevel.Itis
///usedbynormalapplicationsbeinglaunchedwhileUACisenabled.
///(SID:S-1-16-0x2000)
///
///SECURITY_MANDATORY_HIGH_RID-meanshighintegritylevel.Itisused
///byadministrativeapplicationslaunchedthroughelevationwhenUACis
///enabled,ornormalapplicationsifUACisdisabledandtheuserisan
///administrator.(SID:S-1-16-0x3000)
///
///SECURITY_MANDATORY_SYSTEM_RID-meanssystemintegritylevel.Itis
///usedbyservicesandothersystem-levelapplications(suchasWininit,
///Winlogon,Smss,etc.)(SID:S-1-16-0x4000)
///
///</returns>
///<exceptioncref="System.ComponentModel.Win32Exception">
///WhenanynativeWindowsAPIcallfails,thefunctionthrowsaWin32Exception
///withthelasterrorcode.
///</exception>
internalintGetProcessIntegrityLevel()
{
intIL=-1;
SafeTokenHandlehToken=null;
intcbTokenIL=0;
IntPtrpTokenIL=IntPtr.Zero;
try
{
//OpentheaccesstokenofthecurrentprocesswithTOKEN_QUERY.
if(!NativeMethod.OpenProcessToken(Process.GetCurrentProcess().Handle,
NativeMethod.TOKEN_QUERY,outhToken))
{
thrownewWin32Exception(Marshal.GetLastWin32Error());
}
//Thenwemustquerythesizeoftheintegritylevelinformation
//associatedwiththetoken.NotethatweexpectGetTokenInformation
//toreturnfalsewiththeERROR_INSUFFICIENT_BUFFERerrorcode
//becausewe'vegivenitanullbuffer.OnexitcbTokenILwilltell
//thesizeofthegroupinformation.
if(!NativeMethod.GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenIntegrityLevel,IntPtr.Zero,0,
outcbTokenIL))
{
interror=Marshal.GetLastWin32Error();
if(error!=NativeMethod.ERROR_INSUFFICIENT_BUFFER)
{
//Whentheprocessisrunonoperatingsystemspriorto
//WindowsVista,GetTokenInformationreturnsfalsewiththe
//ERROR_INVALID_PARAMETERerrorcodebecause
//TokenIntegrityLevelisnotsupportedonthoseOS's.
thrownewWin32Exception(error);
}
}
//Nowweallocateabufferfortheintegritylevelinformation.
pTokenIL=Marshal.AllocHGlobal(cbTokenIL);
if(pTokenIL==IntPtr.Zero)
{
thrownewWin32Exception(Marshal.GetLastWin32Error());
}
//Nowweaskfortheintegritylevelinformationagain.Thismayfail
//ifanadministratorhasaddedthisaccounttoanadditionalgroup
//betweenourfirstcalltoGetTokenInformationandthisone.
if(!NativeMethod.GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenIntegrityLevel,pTokenIL,cbTokenIL,
outcbTokenIL))
{
thrownewWin32Exception(Marshal.GetLastWin32Error());
}
//MarshaltheTOKEN_MANDATORY_LABELstructfromnativeto.NETobject.
TOKEN_MANDATORY_LABELtokenIL=(TOKEN_MANDATORY_LABEL)
Marshal.PtrToStructure(pTokenIL,typeof(TOKEN_MANDATORY_LABEL));
//IntegrityLevelSIDsareintheformofS-1-16-0xXXXX.(e.g.
//S-1-16-0x1000standsforlowintegritylevelSID).Thereisone
//andonlyonesubauthority.
IntPtrpIL=NativeMethod.GetSidSubAuthority(tokenIL.Label.Sid,0);
IL=Marshal.ReadInt32(pIL);
}
finally
{
//Centralizedcleanupforallallocatedresources.
if(hToken!=null)
{
hToken.Close();
hToken=null;
}
if(pTokenIL!=IntPtr.Zero)
{
Marshal.FreeHGlobal(pTokenIL);
pTokenIL=IntPtr.Zero;
cbTokenIL=0;
}
}
returnIL;
}
5. How to show an UAC shield icon on the UI for tasks that requires elevation?
//Gettheprocesselevationinformation.
boolfIsElevated=IsProcessElevated();
//UpdatetheSelf-elevatebuttontoshowtheUACshieldiconon
//theUIiftheprocessisnotelevated.
this.btnElevate.FlatStyle=FlatStyle.System;
NativeMethod.SendMessage(btnElevate.Handle,NativeMethod.BCM_SETSHIELD,
0,fIsElevated?IntPtr.Zero:(IntPtr)1);
6. How to self-elevate the current process?
//Launchitselfasadministrator
ProcessStartInfoproc=newProcessStartInfo();
proc.UseShellExecute=true;
proc.WorkingDirectory=Environment.CurrentDirectory;
proc.FileName=Application.ExecutablePath;
proc.Verb="runas";
try
{
Process.Start(proc);
}
catch
{
//Theuserrefusedtheelevation.
//Donothingandreturndirectly...
return;
}
Application.Exit();//Quititself
7. How to automatically elevate the process when it's started up?
If your application always requires administrative privileges, such as during an installation step, the operating system can automatically prompt the user for privileges elevation each time your application is invoked.
If a specific kind of resource (RT_MANIFEST) is found embedded within the application executable, the system looks for the <trustInfo> section and parses its contents. Here is an example of this section in the manifest file:
<trustInfoxmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="requireAdministrator"
/>
</requestedPrivileges>
</security>
</trustInfo>
Three different values are possible for the level attribute
a) requireAdministrator
The application must be started with Administrator privileges; it won't run otherwise.
b) highestAvailable
The application is started with the highest possible privileges. If the user is logged on with an Administrator account, an elevation prompt appears. If the user is a Standard User, the application is started (without any elevation prompt) with these standard privileges.
c) asInvoker
The application is started with the same privileges as the calling application.
To configure the elevation level in this Visual C# Windows Forms project, open the project's properties, turn to the Security tab, check the checkbox "Enable ClickOnce Security Settings", check "This is a fulltrust application" and close the application Properies page. This creates an app.manifest file and configures the project to embed the manifest. You can open the "app.manifest" file from Solution Explorer by expanding the Properies folder. The file has the following content by default.
<?xmlversion="1.0"encoding="utf-8"?>
<asmv1:assemblymanifestVersion="1.0"xmlns="urn:schemas-microsoft-com:asm.v1"
xmlns:asmv1="urn:schemas-microsoft-com:asm.v1"xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentityversion="1.0.0.0"name="MyApplication.app"/>
<trustInfoxmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivilegesxmlns="urn:schemas-microsoft-com:asm.v3">
<!--UACManifestOptions
IfyouwanttochangetheWindowsUserAccountControllevelreplacethe
requestedExecutionLevelnodewithoneofthefollowing.
<requestedExecutionLevellevel="asInvoker"uiAccess="false"/>
<requestedExecutionLevellevel="requireAdministrator"uiAccess="false"/>
<requestedExecutionLevellevel="highestAvailable"uiAccess="false"/>
IfyouwanttoutilizeFileandRegistryVirtualizationforbackward
compatibilitythendeletetherequestedExecutionLevelnode.
-->
<requestedExecutionLevellevel="asInvoker"uiAccess="false"/>
</requestedPrivileges>
<applicationRequestMinimum>
<PermissionSetversion="1"
Unrestricted="true"ID="Custom"SameSite="site"/>
<defaultAssemblyRequestpermissionSetReference="Custom"/>
</applicationRequestMinimum>
</security>
</trustInfo>
</asmv1:assembly>
Here we are focusing on the line:
<requestedExecutionLevellevel="asInvoker"uiAccess="false"/>
You can change it to be
<requestedExecutionLevellevel="requireAdministrator"uiAccess="false"/>
to require the application always be started with Administrator privileges.
You may be particularly interested in how to perform the above UAC operations in native VC++ and VB.NET. You can find the answer in CppUACSelfElevation and VBUACSelfElevation sample packages.
Each sample package is accompanied with a ReadMe.txt file that documents the sample in detail.
If you have any feedback regarding the code samples or the entire All-In-One Code Framework project, please feel free to contactcodefxf@microsoft.com.