Forum Discussion
Fetch Email of Login User Using Command or Script
Dear Team,
We are working on retrieving email address of the user joined to Entra ID from Entra-joined Windows devices, specifically while running in a system context.The whoami /upn command successfully returns the joined user’s email address in a user context, but it does not work in a system context, particularly when using an elevated terminal via the psexec utility. We also tested the dsregcmd /status command; however, in a system context, the User Identity tab in the SSO State section only appears when there is an error in AzureAdPrt. Under normal, healthy operating conditions, this command does not provide the user identity or the full domain username.
We would greatly appreciate guidance on how to retrieve the Entra ID joined user’s email address in a system context, especially from those with prior experience in this area.
Thank you for your support.
1 Reply
Method 1: The PowerShell "Get-LoggedOnUser" Approach (Most Recommended)
This is the most reliable and modern method. It involves using PowerShell to query active user sessions and then retrieving the UPN from the user object in Active Directory or Entra ID.
The key is to find the session of the active console user. A SYSTEM script can do this.
Here is a PowerShell script designed to be run as SYSTEM. It will find the currently active, interactive user and get their UPN.
powershell
# Script to be run from a SYSTEM context (e.g., via PsExec, Intune, SCCM)
function Get-ActiveUserUPN {
try {
# Query for active, interactive user sessions
$queryResult = query user
if ($null -eq $queryResult) {
Write-Warning "No active user sessions found."
return $null
}# Find the line corresponding to the 'Active' session
# The output format of 'query user' can be tricky, so we parse it carefully.
$activeSession = $queryResult | ForEach-Object { $_.Trim() } | Where-Object { $_ -like "* console *" -and $_ -like "* Active *"}if ($activeSession) {
# The username is the first part of the string
$userName = ($activeSession -split '\s+')[0]
Write-Verbose "Found active console user: $userName"# Now, get the user's UPN. This requires the Microsoft.Graph.Users module
# or querying local AD if it's a hybrid environment.
# For a pure Entra ID environment, we can check the registry for cached profiles.# --- Reliable Method: Check Registry for Entra ID Profiles ---
$sid = (New-Object System.Security.Principal.NTAccount($userName)).Translate([System.Security.Principal.SecurityIdentifier]).Value
$registryPath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$sid"
if (Test-Path $registryPath) {
$profile = Get-ItemProperty -Path $registryPath
$profilePath = $profile.ProfileImagePath# For Entra ID users, the UPN is often stored in a related key or can be inferred.
# A more direct way is to look at the IdentityCache.
$identityCachePath = "Registry::HKEY_USERS\$sid\Software\Microsoft\IdentityCRL\UserExtendedProperties\$userName"
if (Test-Path $identityCachePath) {
$identityProps = Get-ItemProperty -Path $identityCachePath
# The UPN is often stored in a property named after the user's email/UPN
# This part can be fragile, but let's try to find it.
$upnProperty = $identityProps | Get-Member -MemberType NoteProperty | Where-Object { $_.Name -like '*@*' }
if ($upnProperty) {
return $upnProperty.Name
}
}
}# --- Fallback Method: If the above fails, try another registry location ---
# This is where Entra ID caches user info for login
$entraProfilesPath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\UserTile"
$userTileKey = Get-ChildItem -Path $entraProfilesPath | Where-Object { (Get-ItemProperty -Path $_.PSPath).LoggedOnUser -eq "NT AUTHORITY\SYSTEM" -and (Get-ItemProperty -Path $_.PSPath).ProfileImagePath -like "*$userName*"}
if ($userTileKey) {
$upn = (Get-ItemProperty -Path $userTileKey.PSPath).UserPrincipalName
if ($upn) {
return $upn
}
}Write-Warning "Could not reliably determine UPN for user '$userName'."
return $null
}
else {
Write-Warning "No active console session found."
return $null
}
}
catch {
Write-Error "An error occurred: $($_.Exception.Message)"
return $null
}
}# --- Execution ---
$userUPN = Get-ActiveUserUPN
if ($userUPN) {
Write-Host "Detected Entra ID User UPN: $userUPN"
} else {
Write-Host "Failed to detect Entra ID User UPN."
}How to use this:
- Save the script as a .ps1 file (e.g., GetUserUPN.ps1).
- Run it from your elevated SYSTEM context using PsExec: psexec -s -i powershell.exe -ExecutionPolicy Bypass -File C:\path\to\GetUserUPN.ps1
This script is the most robust because it actively looks for the logged-on user and then tries to find their associated UPN from the places Windows caches this information for Entra ID accounts.
Method 2: The Registry Dive (Direct but Potentially Brittle)
If you are certain there will only ever be one primary Entra ID user on the device, you can often find their UPN directly in the registry. This is faster but can be less reliable on multi-user devices.
The key location is related to the Cloud Account Provider (CloudAP).
PowerShell Snippet (to be run as SYSTEM):
powershell
# This path contains information about cached cloud-provider users.
$path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\CloudAP\Microsoft\EntraId\User"try {
# Get all subkeys (each representing a user profile)
$userKeys = Get-ChildItem -Path $path -ErrorAction Stopif ($userKeys.Count -gt 0) {
# Assuming the first or only user is the primary one.
# In a real-world script, you might need more logic to pick the right one.
$primaryUserKey = $userKeys[0]# Get the UPN from the 'Username' property of that key.
$upn = (Get-ItemProperty -Path $primaryUserKey.PSPath).Usernameif ($upn) {
Write-Host "Found UPN in CloudAP cache: $upn"
} else {
Write-Warning "Found user key but no 'Username' property."
}
} else {
Write-Warning "No Entra ID user profiles found in CloudAP cache."
}
}
catch {
Write-Error "Failed to access registry key. Error: $($_.Exception.Message)"
}Why this works: This registry hive is used by the Cloud Authentication Provider to cache details about the Entra ID users who have logged into the machine. It's a more direct query for the information you want.
Method 3: The Scheduled Task "Impersonation" Trick (Complex but Powerful)
This is an advanced technique. You can use the SYSTEM account to create a temporary scheduled task that is configured to run as the currently logged-on user.
- From SYSTEM context: Your script first identifies the active user's username (e.g., using query user as in Method 1).
- Create a Scheduled Task: Your script then dynamically creates a scheduled task using schtasks.exe or the ScheduledTasks PowerShell module.
- Action: The task is set to run a simple command like whoami /upn > C:\temp\upn.txt.
- Run As: This is the crucial part. The task is configured to run under the security context of the user you identified in step 1 (e.g., DOMAIN\user).
- Trigger: The task is set to run immediately.
- Execute and Clean Up: The script runs the task, waits a few seconds for the output file to be created, reads the content of the file (C:\temp\upn.txt), and then deletes the temporary task and the output file.
This method is powerful because it effectively "borrows" the user's context to run a command that only works in a user context. However, it is much more complex to script reliably and has more moving parts.
Recommendation
For your use case, Method 1 (The PowerShell "Get-LoggedOnUser" Approach) is the most balanced and recommended solution. It is robust enough to handle most scenarios, relies on standard PowerShell capabilities, and doesn't require complex impersonation tricks. It directly queries the system for the active user and then intelligently inspects the registry for the information associated with that user's session.