Disabling Admin UAC with Powershell

July 31st, 2009

Well apparently some people don’t like User Account Control getting in the way of the Administrator account(s), and so they need a way to disable this annoying
behavior. Here’s a quick function I threw together today at the request of a friend, that will do just that. Please excuse the formatting…

function Set-AdminUAC([int] $value = 0) {
$computers	= @($input);
if ($computers.count -lt 1) {
	$computers += @('.');
}
$results	= @{};
$hkey_lm	= 'LocalMachine';
$hkey_cr	= 'ClassesRoot';
$path_system	= 'Software\Microsoft\Windows\CurrentVersion\Policies\System';
$path_clsid	= 'CLSID';
$id_notify	= '{FD6905CE-952F-41F1-9A6F-135D9C6622CC}';
$prompt_admin	= 'ConsentPromptBehaviorAdmin';

foreach ($computer in $computers) {
	$success	= $false;

	trap { ;
	continue } $reg_lm	= [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($hkey_lm, $computer);
	if ($? -eq $false) {
		$results.$computer = $success;
		continue;
	}
	$reg_cr		= [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($hkey_cr, $computer);

	$key_system	= $reg_lm.OpenSubKey($path_system, $true);
	if ($key_system -ne $null) {
		foreach ($index in 0..1) {
			$value_admin	= $key_system.GetValue($prompt_admin);
			if ($value_admin -eq $value) {
				$success = $true;
				break;
			}
			else {
				trap { ;
				continue } $key_system.SetValue($prompt_admin, $value, 'Dword') | out-null;
				if ($?) {
					$key_system.Flush() | out-null;

					$key_clsid	= $reg_cr.OpenSubKey($path_clsid, $true);
					$subkeys	= @($key_clsid.GetSubKeyNames());
					if (($key_clsid -ne $null) -and ($subkeys -contains $id_notify)) {
						$key_clsid.DeleteSubKey($id_notify) | out-null;
						$key_system.Flush() | out-null;
						$key_clsid.Close() | out-null;
					}
				}
			}
		}
		$key_system.Close() | out-null;
	}
	$reg_lm.Close() | out-null;
	$reg_cr.Close() | out-null;
	$results.$computer = $success;
}
	return $results;
}


I allowed for having the ability to set it to whichever value you desire, since we might have a reason for re-enabling or changing the Admin UAC later on.

Let’s look at it in detail. First, declare the function, passing in an argument for the value that we want to set ‘ConsentPromptBehaviorAdmin’ to. Then, take in a list of computer names from the piped input. If nothing is piped in, we assuming that the function is to be executed against the local machine (denoted by the ‘.’). Also notice that we default to a value of ‘0′ if no argument was given, which is to disable (see below for a link explaining the possible values for the registry property).

function Set-AdminUAC([int] $value = 0) {
	$computers	= @($input);
	if ($computers.count -lt 1) {
		$computers += @('.');
	}

Next, set up our variables to store the results in, and set the registry paths and properties that we’ll be looking at. Then, iterate over each computer name that was piped in.

$results	= @{};
$hkey_lm	= 'LocalMachine';
$hkey_cr	= 'ClassesRoot';
$path_system	= 'Software\Microsoft\Windows\CurrentVersion\Policies\System';
$path_clsid	= 'CLSID';
$id_notify	= '{FD6905CE-952F-41F1-9A6F-135D9C6622CC}';
$prompt_admin	= 'ConsentPromptBehaviorAdmin';

foreach ($computer in $computers) {

We default to assuming that the change was not successful, unless something happens later that causes the change to be successful. Then, we attempt opening the HKey ‘LocalMachine’ of the remote registry. If this fails, we log it as a failure and then skip to the next computer. We also attempt opening ClassesRoot, but we don’t assume failure if this doesn’t work, since we only want to make a secondary change there.

Next, open the ‘Software\Microsoft\Windows\CurrentVersion\Policies\System’ subkey, and pass a value of true for the second parameter, since we want to open it for writing (as in, not read-only). We move along to the inner statements if opening the subkey worked.

$success	= $false;

trap { ;
continue } $reg_lm	= [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($hkey_lm, $computer);
if ($? -eq $false) {
	$results.$computer = $success;
	continue;
}
$reg_cr		= [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($hkey_cr, $computer);
$key_system	= $reg_lm.OpenSubKey($path_system, $true);
if ($key_system -ne $null) {

The following will look a bit unusual. We basically want to do the following twice, checking each time to see if the current value of the ‘ConsentPromptBehaviorAdmin’ property is set to what we want it set to. If it is, we consider it a success, and we break out of the loop. If it isn’t, we attempt to make the registry change.

foreach ($index in 0..1) {
	$value_admin	= $key_system.GetValue($prompt_admin);
	if ($value_admin -eq $value) {
		$success = $true;
		break;
	}
	else {

If the current value of ‘ConsentPromptBehaviorAdmin’ does not match our desired value, we attempt to set the value. If it works, we commit the change, then attempt to remove the subkey of ClassesRoot that causes related notifications to be displayed. This isn’t strictly necessary, but I added it to the script since it’s a common request that relates to UAC changes.

trap { ;
continue } $key_system.SetValue($prompt_admin, $value, 'Dword') | out-null;
if ($?) {
	$key_system.Flush() | out-null;

	$key_clsid	= $reg_cr.OpenSubKey($path_clsid, $true);
	$subkeys	= @($key_clsid.GetSubKeyNames());
	if (($key_clsid -ne $null) -and ($subkeys -contains $id_notify)) {
		$key_clsid.DeleteSubKey($id_notify) | out-null;
		$key_system.Flush() | out-null;
		$key_clsid.Close() | out-null;
	}
}

Finally, close the registry keys that were opened, and add the result to the hash. Once we’re done looping over every computer that was piped in, we return the resulting hash.

				}
			}

			$key_system.Close() | out-null;
		}
		$reg_lm.Close() | out-null;
		$reg_cr.Close() | out-null;
		$results.$computer = $success;
	}
	return $results;
}

Let’s test it.

PS > Set-AdminUAC

Name                           Value
----                           -----
.                              True

PS > 'server_that_doesnt_exist' | Set-AdminUAC 1

Name                           Value
----                           -----
server_that_doesnt_exist       False

So that’s it. This is just one way of doing it, and is actually one of the more inefficient ways to accomplish this task. If you’d like to see documentation on the ‘ConsentPromptBehaviorAdmin’ property, please check the below link.

http://msdn.microsoft.com/en-us/library/cc206328(PROT.10).aspx

Categories: PowerShell, Server 2008

Tags: , , Leave a comment

Leave a comment

Feed

http://www.techmumbojumblog.com / Disabling Admin UAC with Powershell