How do I get the current username in Windows PowerShell?
Asked Answered
L

15

494

How do I get the current username in Windows PowerShell?

Lao answered 18/1, 2010 at 11:50 Comment(0)
L
574

I found it:

[Environment]::UserName
$Env:UserName

There is also:

$Env:UserDomain
$Env:ComputerName
Lao answered 18/1, 2010 at 11:52 Comment(6)
The answer is just using a static .NET method from within Powershell which might be a useful technique to use elsewhere.Lao
Not currently logged user but simply environment variables! Do not answer the question.Cw
This does not work on linux...Strage
@Strage Yes, because this question is tagged [windows] ;-)Gyromagnetic
This is NOT a secure method. It's trivially easy to circumvent, and it may go wrong if someone has been messing with their environment variables. Use the WindowsIdentity call to get what Windows really thinks.Archdeaconry
To demonstrate the ability of the user to change this environment variable, run the commands: $env:UserName; $env:UserName = "superadmin"; $env:UserName. This may be acceptable for convenience non-critical uses, but should not be used for security or audit logs.Rhone
F
281

On Windows, you can:

[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
Fiddle answered 18/1, 2010 at 11:54 Comment(6)
This is the most secure answer because $env:USERNAME can be altered by the user, but this will not be fooled by doing that.Joel
@KevinPanko True, but at the point that you can't trust your user, there are other, more philosophical questions that need to be asked. ;-)Ollieollis
This method includes the domain name and username. Definitely beneficial if you have multiple domains in play.Hadlock
Works as expected. Tested for url address reservation.Coccus
Also, this looks to work in PowerShell 6 as well, meaning it's cross platform (.Net Standard) compatible. Thought it was worth mentioning since I questioned it when I saw the namespace.Yuonneyup
This even works correctly for users like NT AUTHORITY\SYSTEM, $env:USERNAME equals to <computername>$ in this case, and $env:USERDOMAIN is just domain of your computerGoetz
M
206

I thought it would be valuable to summarize and compare the given answers.

If you want to access the environment variable:

(easier/shorter/memorable option)

  • [Environment]::UserName -- @ThomasBratt
  • $env:username -- @Eoin
  • whoami -- @galaktor

If you want to access the Windows access token:

(more dependable option)

  • [System.Security.Principal.WindowsIdentity]::GetCurrent().Name -- @MarkSeemann

If you want the name of the logged in user

(rather than the name of the user running the PowerShell instance).

  • $(Get-CimInstance Win32_ComputerSystem | select username).username -- @TwonOfAn on this other forum and updated based on information in comments.

Comparison

@Kevin Panko's comment on @Mark Seemann's answer deals with choosing one of the categories over the other:

[The Windows access token approach] is the most secure answer, because $env:USERNAME can be altered by the user, but this will not be fooled by doing that.

In short, the environment variable option is more succinct, and the Windows access token option is more dependable.

I've had to use @Mark Seemann's Windows access token approach in a PowerShell script that I was running from a C# application with impersonation.

The C# application is run with my user account, and it runs the PowerShell script as a service account. Because of a limitation of the way I'm running the PowerShell script from C#, the PowerShell instance uses my user account's environment variables, even though it is run as the service account user.

In this setup, the environment variable options return my account name, and the Windows access token option returns the service account name (which is what I wanted), and the logged in user option returns my account name.


Testing

Also, if you want to compare the options yourself, here is a script you can use to run a script as another user. You need to use the Get-Credential cmdlet to get a credential object, and then run this script with the script to run as another user as argument 1, and the credential object as argument 2.

Usage:

$cred = Get-Credential UserTo.RunAs
Run-AsUser.ps1 "whoami; pause" $cred
Run-AsUser.ps1 "[System.Security.Principal.WindowsIdentity]::GetCurrent().Name; pause" $cred

Contents of Run-AsUser.ps1 script:

param(
  [Parameter(Mandatory=$true)]
  [string]$script,
  [Parameter(Mandatory=$true)]
  [System.Management.Automation.PsCredential]$cred
)

Start-Process -Credential $cred -FilePath 'powershell.exe' -ArgumentList 'noprofile','-Command',"$script"

(you may need a hyphen before noprofile, like so)

Start-Process -Credential $cred -FilePath 'powershell.exe' -ArgumentList '-noprofile','-Command',"$script"
Miss answered 29/4, 2015 at 21:49 Comment(5)
For PowerShell 6 on Mac OS X and Linux, [Environment]::UserName is the best option, as it works cross platform. whoami seems to also work, but depends on the whoami tool being available on the platform.Piker
For Powershell 6 on Windows, $env:USERNAME produces SYSTEM unless I run-as-administrator, while [Environment]::UserName] yields my username either way.Arvizu
Seem like the Get-WmiObject method no longer works in pwsh. Even tried to import compatibility module and the Microsoft.PowerShell.Management that has the cmdlet. Any idea what's happening?Sneck
Correct. It was fazed over to Get-CimInstance quite a while back for performance reasons... and CIM has to be used over WMI in v6 for cross-compatibility reasons. If you see a command with GWMI, check if you can do GCIM instead.Anfractuosity
In PS6+ you can use this: $(Get-CimInstance Win32_ComputerSystem | select username).usernameRifling
M
105

$env:username is the easiest way

Mannish answered 14/10, 2011 at 12:59 Comment(2)
You can assign it this way, and build up directories and what not.Damron
@Damron What not? You cannot open user folder with Run (Windows + R) using that.Gpo
S
58

I'd like to throw in the whoami command, which basically is a nice alias for doing %USERDOMAIN%\%USERNAME% as proposed in other answers.

Write-Host "current user:"
Write-Host $(whoami)
Sabinasabine answered 14/11, 2011 at 9:8 Comment(7)
it works for me on PS version 2. Are you saying it was dropped in PS3? C:\>powershell Windows PowerShell Copyright (C) 2009 Microsoft Corporation. All rights reserved. PS C:\> whoami mydomain\myusernameSabinasabine
$env:USERNAME can be altered by the user, but this will not be fooled by doing that.Joel
whoami wins for interactive use. It's short enough that I can remember how to type it without consulting SO :-)Guenna
Not a thing in Nano Server. Don't use it in scripts, do the correct thing ([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)Yogini
whoami is an executable. It can't be removed from PowerShell. It could potentially be removed from Windows, but it's still there as of non-Nano Windows Server 2012.Fraze
whoami has the added benefit been able to return the UPN on a Azure AD joined computer for which %USERNAME% isn't much use. For example, $Env:Username returns RobNicholson but my Azure AD username is really [email protected]Team
Do note, that if you use a remote management system that can utilize Powershell scripts, whoami will return SYSTEM rather than the user logged in.Splinter
B
39

[Environment]::UserName returns just the user name. E.g. bob [System.Security.Principal.WindowsIdentity]::GetCurrent().Name returns the user name, prefixed by its domain where appropriate. E.g. SOMEWHERENICE\bob

Boz answered 14/7, 2011 at 12:19 Comment(0)
R
23

Now that PowerShell Core (aka v6) has been released, and people may want to write cross-platform scripts, many of the answers here will not work on anything other than Windows.

[Environment]::UserName appears to be the best way of getting the current username on all platforms supported by PowerShell Core if you don't want to add platform detection and special casing to your code.

Reiss answered 15/3, 2018 at 20:37 Comment(0)
H
18

I have used $env:username in the past, but a colleague pointed out it's an environment variable and can be changed by the user and therefore, if you really want to get the current user's username, you shouldn't trust it.

I'd upvote Mark Seemann's answer: [System.Security.Principal.WindowsIdentity]::GetCurrent().Name

But I'm not allowed to. With Mark's answer, if you need just the username, you may have to parse it out since on my system, it returns hostname\username and on domain joined machines with domain accounts it will return domain\username.

I would not use whoami.exe since it's not present on all versions of Windows, and it's a call out to another binary and may give some security teams fits.

Hamfurd answered 24/1, 2017 at 17:21 Comment(1)
Since the OP did ask about Windows-Powershell, that's valid, but [Environment]::UserName is less typing, independent of $env:username and cross-platform: See pastebin.com/GsfR6HrpArvizu
D
11

Just building on the work of others here:

[String] ${stUserDomain},[String]  ${stUserAccount} = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name.split("\")
Delly answered 4/8, 2016 at 16:42 Comment(0)
S
7
$username=( ( Get-WMIObject -class Win32_ComputerSystem | Select-Object -ExpandProperty username ) -split '\\' )[1]

$username

The second username is for display only purposes only if you copy and paste it.

Stalingrad answered 6/6, 2019 at 19:56 Comment(3)
$fullname=Get-WMIObject -class Win32_ComputerSystem | Select-Object -ExpandProperty username $username=$fullname.Replace("DOMAIN\","") $usernameStalingrad
This one works the best if you want the user logged on to the machine, not the user running the powershell session. If you are running a script as system and want to know what user is logged on to the machine, the env variables dont help.Richter
As per my investigation it seems that it is better to use Get-CIMInstance instead of Get-WMIObject. Please refer to the article here.Depalma
B
1

I didn't see any Add-Type based examples. Here is one using the GetUserName directly from advapi32.dll.

$sig = @'
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool GetUserName(System.Text.StringBuilder sb, ref Int32 length);
'@

Add-Type -MemberDefinition $sig -Namespace Advapi32 -Name Util

$size = 64
$str = New-Object System.Text.StringBuilder -ArgumentList $size

[Advapi32.util]::GetUserName($str, [ref]$size) |Out-Null
$str.ToString()
Besprinkle answered 3/8, 2014 at 20:9 Comment(4)
Please explain what this code is doing and why it would be more useful than one of the shorter methods.Livraison
@BenjaminHubbard The question does not ask for the shortest method, it asks how to accomplish the feat with powershell. This does the trick differently then the other examples by calling the function inside the dll and using the Add-Type method to access .NET.Besprinkle
While this is a novel code block, it would be great if I knew what the heck it was doing. Can you annotate it with comments, maybe? Thanks!Ollieollis
I almost wanted to upvote, since I saw merit to the proposal. Yet the code has some flaws: it introduces a new namespace, it uses a magic constant (64) which value is not what the doctor prescribed (should be UNLEN+1, and UNLEN is 256), it disregards any error which might be returned from GetUserName (through it preserves GetLastError, a good point), it does not clean up the string buffer; and probably some others. And as others said, comments are sorely missing, too.Alber
L
0

Sometimes the Username attribute has no data in Win32_ComputerSystem even though there's a user signed in. What works for me is to use quser and parse the output. It's not perfect, but it works. E.g.:

$quserdata = @()
$quserdata = quser
$userid = ($quserdata[1] -split ' ')[1]
$userid 

Note: if this is run as the user who is logged in, quser adds '>' symbol to the output. Then you need to get rid of that symbol, but mostly this is needed for code run as system or another account than the one that is logged in.

Lilililia answered 12/12, 2022 at 16:44 Comment(0)
M
-2

If you're used to batch, you can call

$user=$(cmd.exe /c echo %username%)

This basically steals the output from what you would get if you had a batch file with just "echo %username%".

Monro answered 6/7, 2017 at 21:37 Comment(1)
I'm downvoting because: a) You the $(...) is superfluous: $a = cmd.exe /c echo %username% works, b) it's not portable, c) it doesn't actually answer the question of how to do it in powershell, it answers how to do it in dos, and it's better to give a man a fishing pole than give him a fish, e.g. powershell puts environment variables into $env, so %username% = $env:username.Arvizu
P
-3

I find easiest to use: cd $home\Desktop\

will take you to current user desktop

In my case, I needed to retrieve the username to enable the script to change the path, ie. c:\users\%username%. I needed to start the script by changing the path to the users desktop. I was able to do this, with help from above and elsewhere, by using the get-location applet.

You may have another, or even better way to do it, but this worked for me:

$Path = Get-Location

Set-Location $Path\Desktop

Playwriting answered 1/2, 2019 at 14:23 Comment(2)
Making any assumptions based on the home directory is bound to only work under very specific conditions.Arrest
If you are working in a powershell terminal and just quickly want to find out what user you are, then typing "ls ~" should do the trick. Like the above poster, there might be exceptions, and this is definitely not good for scripts, so use Edouard Poor's example in that case.Raul
C
-4

In my case, I needed to retrieve the username to enable the script to change the path, ie. c:\users\%username%\. I needed to start the script by changing the path to the users desktop. I was able to do this, with help from above and elsewhere, by using the get-location applet.

You may have another, or even better way to do it, but this worked for me:

$Path = Get-Location

Set-Location $Path\Desktop
Copenhagen answered 30/12, 2015 at 16:49 Comment(1)
Welcome to Stack Overflow! This is equivalent to Set-Location Desktop. (Get-Location merely returns the current location, which is implicit for a Set-Location with a relative path.)Ollieollis

© 2022 - 2024 — McMap. All rights reserved.