Something like su(1) for PowerShell and Console

If you have your day-to-day account configured as a limited user and not a member of the Administrators group, you have to elevate to switch users or use the runas service to do some system configuration tasks. If you already have a shell open anyway, the runas comand-line is probably what you want, but the syntax of the command is a little verbose. I have a basic su-like su for PowerShell that opens a new PowerShell session in a new Console window running with the credentials you gave to su. By default it tries to log you in as the built-in administrator account (which is disabled by default on Windows Vista/7).

su.ps1

#emulate UNIX su behavior
#start a new powershell instance with a different user account context

param( [string] $username )

function Substitute-User( [String] $username )
{
	if( !$username )
	{
		#look up the built-in Administrator account using WMI. 
		#the built-in administrator has a SID that starts with S-1-5 and ends with -500.
		$accts = get-wmiobject win32_useraccount
		foreach( $acct in $accts )
		{	
			if( $acct.SID -match '^S-1-5-.+-500$' )
			{ 
				$username = $acct.Caption
				if( $username -match "[^\\]+$" )
				{	
					$username = $matches[0] 
				}
				break
			} 
		}
	}
	$credential = Get-ConsoleCredential( $username )
	$startinfo = new-object Diagnostics.ProcessStartInfo
	$startinfo.UseShellExecute = $false
	$startinfo.FileName = "$env:programfiles\Console2\Console.exe"
	$startinfo.UserName = $credential.UserName
	$startinfo.Password = $credential.Password
	$startinfo.Arguments = "-r $pshome\powershell.exe -d `"$pwd`""
	$startinfo.WorkingDirectory = $pwd

	trap [ComponentModel.Win32Exception]
	{
		if( $_.Exception.NativeErrorCode -eq 267 )
		{
			write-host "$pwd is an invalid directory for $username."
			write-host "Starting PowerShell in ${env:SystemRoot}\system32."
			$startinfo.Arguments = "-r $pshome\powershell.exe -d ${env:SystemRoot}\system32"
			$startinfo.WorkingDirectory = "${env:SystemRoot}\system32"
			$null = [Diagnostics.Process]::Start( $startinfo )
		}
		else 
		{	
			$_.Exception.Message
		}
		continue
	}
	$null = [Diagnostics.Process]::Start( $startinfo )
}

#Generate a PSCredential object without creating a pop-up security dialog like 
#the built-in get-credential cmdlet.
function Get-ConsoleCredential( [String] $username=$( read-host 'Username' ) )
{
	while( !($username) )	
	{
		$username = read-host 'Username'
	}
	$passwd = read-host -asSecureString 'Password'
	new-object Management.Automation.PSCredential $username, $passwd
}

Substitute-User $username

One Response to Something like su(1) for PowerShell and Console

  1. Rex says:

    Neat, didn’t know about Console 2. Sounds like the script will launch a new Console2 process, spawning a new window rather than a new tab. Somewhat defeats the purpose of using Console 2! I found another Console Emulator that could supports opening a session in a new tab if a Console Emu process already exists by virtue of researching the problem, thought I’d share.

    http://superuser.com/questions/420444/console2-open-new-tab-in-existing-session-from-cmd

Leave a comment