UAC and group policies
From hereon we will assume that you have read the article above and we will adopt the term "elevate" as
prompting the user for permission to change token. The article above also explains policy settings and
one interesting thing about the UAC policy settings is that they are per-machine and effectively all-or-nothing
settings. It would make sense to create one domain admin user that is not under User Account Control, which could
be used for automation tasks. But this is not possible by design by Microsoft.
Understanding permissions and privileges
To fully understand what it means that administrators have multiple tokens, let's look
at this from a more practical angel. If you are new to Windows 7 scripting and
User Account Control, here is a little surprise that will put things in perspective.
We will assume that you, as the executing user, are a local administrator and that you
are under User Account Control. Let us try to run a very simple script:
WriteRegistry HKLM\Software\Acme Corporation\Test,Test
Pretty straight-forward, but this happens when we execute the script:
The reason this happens is that the executing user has the
permission to write
to the registry, but not the
privilege to do so. So even if you have permission
to change any system-wide settings like the machine part of the registry, system files or any
other setting that is not per-user, UAC will block. That is in essence the point of UAC. By default you
cannot change system-wide settings, even if you are administrator.
So let's go back to the Microsoft article again and look at the "UAC Architecture" section, which says:
"When an administrator logs on, the user is granted two access tokens: a full administrator access token and
a "filtered" standard user access token. By default, when a member of the local Administrators group logs on,
the administrative Windows privileges are disabled and elevated user rights are removed, resulting in the standard user access token."
The reason we are not allowed to set the registry key is that we are now running a sub-process of the top
explorer.exe on the drawing. This means that we need to make sure that we are executing the script
with the full administrator access token. For this reason there is a command called "ElevateUser".
If we use this command before setting the registry key, the script will look like this:
ElevateUser
WriteRegistry HKLM\Software\Acme Corporation\Test,Test
If the executing user is not under User Account Control, the command does nothing. But if the
executing
is under User Account Control, the script will stop and ask for permission
to continue:
Consequence
So does this mean that it is not possible to do any kind of automation that requires
administrative permission and privilege? Well, it certainly means that some options are
out. For example, if you wanted to set a registry key in the machine part of the registry
or install an application from a logon script, it would normally be possible to include a
script that runs as a domain admin user and then set the key or install the application.
This cannot be done, if UAC is enabled for administrators, because it wouldn't be possible
to ask this user for UAC permission - that is, if you could live with the UAC halting at all.
There are 4 additional commands that will prompt for permission to elevate, if UAC is enabled:
LaunchElevated, LaunchScriptElevated, RunElevated and RunScriptElevated. Obviously these commands
are not usable for fully automated processes, but there are scenarios, where one could live with
the UAC blocking before continuing script execution. For example, if you create a script with a
menu that executes jobs on the local machine and this menu is started manually by for example help
desk operators. In such a case, one could live with an initial prompt to continue.
Alternatives when UAC is enabled for administrators
So we can conclude that if UAC is enabled for administrators, some automation options are out.
It would not be possible for example to install software from a logon script,
as shown
here. But there are alternatives - and they
might be preferred, UAC or no UAC, but they require a little more work. You could say that just changing
executing user in a logon script is a bit of a lazy approach, but it works and it's the simplest way to do it.
So if users and administrators are under User Account Control, what are the options then? Well, the local system account
is not under User Account Control and scheduled tasks are not either, even if the executing user is under User Account Control.
So one option to get automation is to simply package a script inside an MSI package and deploy that through group policies.
Please refer to the
Deploying applications to server farms example and
the
Compiling scripts into MSI files page for more details.
Another approach is using startup scripts, as described
here.
Startup scripts also runs as the local system account and as mapping network drives and reading files off network
shares are not limited by UAC, the system account can freely use the LogonUser command to establish network
credentials and then read required files from the network.
Disabling UAC without group policies
If you are running a network using Windows 2003 domain controllers or you for other reasons cannot set UAC
registry keys through group policies, you can set the EnableLUA value under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
to 0 on client computers manually. There are a number of ways to do this, for example:
- Use a post-automation script for OS installation as shown here and set the registry value from this script.
- Set the registry value from a startup script.
- In case of Windows 2003 domain controllers: Create your own custom .adm file and set the value this way.
You only need to set this registry value once per computer, but you cannot just change the executing user
to an administrator from a logon script and set the value, because you will run into the "chicken or the egg" dilemma.
UAC will block the user elevation needed to disable UAC. But a lazy and practical approach could be to include the below
snippet in the regular logon script, which will work under the assumption that eventually an
administrator will log on to all computers, for example when the computer was originally installed.
If an administrator logs on to a computer with UAC enabled, this user has the permission, but not the privilege
to set the registry value and the ElevateUser command will therefore ensure that the administrator also
has the privileges to change the value.
If [RegistryValue HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA]<>0 And UserIsLocalAdmin Then
ElevateUser
WriteRegistry HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA,0,REG_DWORD
RefreshEnvironment
End If
The RefreshEnviroment command will tell Windows that there is change
in the environment and enforce the change right away, whereas if this command was not issued, UAC will be disabled
from next reboot. As UAC is a per-machine setting, once the setting is changed in the registry, it will be enforced
for all users on the computer.
KB937624 - Missing drive letters for Admins
One final note about UAC that you should be aware of is Microsoft Knowledge Base article 937624.
Because administrators have two access tokens with UAC, these two tokens do not share their network
connections by default. This means that you can run into an issue where your logon script maps
drives for one token, but you will not see them with the other. This is only an issue for
administrators.
You can work around this by changing the default behavior by setting the DWORD registry value EnableLinkedConnections to 1
under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System through policies, a startup script or a maintenance scheduled task. Please refer to the
Knowledge Base article for more information:
http://support.microsoft.com/kb/937624.