July 24, 2011

Get the active user on Windows 7

Changes in the Windows 7 architecture mean that when a SYSTEM process needs to interact with a user session or profile it has to identify the “active user”. This post provides script methods that can be used to achieve this.

Multiple logged on sessions are a fact of life with Windows 7. If you think enabling the “Hide entry points for Fast User Switching” policy settings changes this, think again. If Remote Desktop is enabled multiple sessions can be running even if that policy is enabled. Also, advanced users may know about TSDISCON.EXE, allowing them to disconnect their session without logging off and start a new one

The key difference between Windows 7 and a Windows Server is that, on Win7, only one session can be active at a time. The others are disconnected.

Note that the active session is not necessarily the console session. A remote desktop connection can become the active session, disconnecting the console user.

So what methods are available to get the user id of the active user? The following are two options that are readily available.

1) QUSER / QUERY USER / QUERY SESSION
(These are all similar so I’ll focus on QUSER)

QUSER.EXE is built into Windows 7 and will list all the sessions on the local or remote computer, showing their state (active or disconnected). Only the basic username is shown – not the domain/computer it comes from.

QUser

Admin rights are only required when querying remote sessions.

2) PSTerminalServices Module

PSTerminalServices is a Powershell module by Shay Levy, available from the MSDN code gallery. It needs to be installed on each client or made available on a network share with an update to the user’s $ENV:PSMODULEPATH.

The Get-TSSession cmdlet provides the required information, including the domain/computername of the Username.

Import-Module PSTerminalServices
Get-TSSession


Get-SessionSo how can we take this a step further and update the user’s profile?


The following Powershell script uses the Win32_UserProfile WMI Class to parse the output from QUSER and get the SID and the profile path of the active user.


Once you have the that information, you can write to C:\USERS\<Username> or HKU\<SID>\…

function Get-ActiveUser {
<#
.SYNOPSIS
Get the Windows 7 active user

.DESCRIPTION
Returns the SID and Profile path of the active user on a Windows 7 system.
Uses QUSER.EXE to list the logged on user.

.EXAMPLE
PS C:\> Get-ActiveUser

SID ProfilePath
--- -----------
S-1-5-21-813418204-1865341169-839522115-1111 C:\Users\infguy

.OUTPUTS
PSObject
#>
[CmdletBinding()]
Param()

PROCESS{
$LoggedOn = quser | Select-String "Active"
Write-Verbose "LoggedOn = $LoggedOn"

If($LoggedOn){

#Parse output line to extract username
$LoggedOn -match "^>([\S]*)" | Out-Null
if($Matches){
# There should be only one entry that matches ">Username"
$User = $Matches[1]

If($User){
# Match the loaded profiles on the "LocalPath" attribute
$Profile = Get-WmiObject -Class Win32_UserProfile | Where-Object{($_.Loaded -eq "True") -and ($_.LocalPath -like "*\$user")}
Write-Verbose "Profile = $Profile"

$SID = $Profile | Foreach-object{"$($_.SID)"}
$ProfilePath = $Profile | Foreach-object{"$($_.LocalPath)"}

# Write output
New-Object -TypeName PSObject -Property @{
SID = $SID
ProfilePath = $ProfilePath
}

}else{
Write-Error "Couldn't get username"
}
}else{
Write-Error "Couldn't match Quser output "
}
}else{
Write-Verbose "No active user found."
}

}

END{}

}

No comments:

Post a Comment