0

I am writing a PowerShell script which will be used on GNU+Linux and Windows.

I need a way to retrieve the current username.

If the username is composed with a domain name (domain\username), then I would like the username part.

The script should work with older versions of PowerShell.

A similar question already exists but is focused on Windows (some comments say that Linux should not be a thing because the question is tagged Windows). Many answers don't work on GNU+Linux. What is the best multi-OS way?

1
  • 1
    Why not using a condition? If (Linux) then {this way} else {that way} .... 🤷🏼‍♂️ Commented Jun 16 at 8:25

3 Answers 3

3

[Environment]::UserName is a cross-platform way to obtain the effective[1] current username, because it uses appropriate platform-native API calls behind the scenes.

Note that on Windows the name returned does not include the domain-name part (a concept that is n/a to Unix-like platforms); use [Environment]::UserDomainName to get the NTLM (non-DNS) form of the domain name on Windows; on Unix-like platforms always and on Windows for non-domain-joined machines, said property returns the (unqualified) machine name.


Note:

Using environment variables is an option too, but is susceptible to tampering / being out of sync with the effective user identity.

If you want to rely on them nonetheless, you can use (assumes PowerShell (Core) 7, which is the only cross-platform PowerShell edition):

$IsWindows ? $env:USERNAME : $env:USER 

If a given script must also run in Windows PowerShell (the legacy, ships-with-Windows, Windows-only edition of PowerShell whose latest and last version is 5.1):

($env:USER, $env:USERNAME)[$env:OS -eq 'Windows_NT'] 

All that said: [Environment]::UserName (a) works in both PowerShell editions and (b) is robust (not susceptible to tampering / being out of sync).


[1] Effective means that the username of the user identity associated with the current thread is reported; while this is the same identity as the one associated with the current logon session by default, it may differ if the current thread is impersonating a different user identity.

Sign up to request clarification or add additional context in comments.

Comments

0

Here is a candidate function.

function Get-Username(){ $value = $null $system = [System.Environment]::OSVersion.Platform if ($system -ieq "Win32NT") { $value = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name } elseif ($system -ieq "Unix") { $value = $( whoami ) } else { throw New-Object System.NotSupportedException("Getting username is not supported on this platform"); } $parts = $value -split '\\' return $parts[($parts.Count - 1)] } 

OS check: I'm not sure this is perfect

Getting username: I believe theses are the most reliable methods for each OS

PowerShell version: works with v5.1 (Windows) and v7.4 (Windows, GNU+Linux)

4 Comments

FYI about OS check: [System.Enum]::GetNames([System.PlatformID]) -join ", " yields Win32S, Win32Windows, Win32NT, WinCE, Unix, Xbox, MacOSX, Other.
Thank you @JosefZ! The documentation indicates the other values are “no longer in use”; except for Other. It seems safe as-is. Do you think I am missing something?
[Environment]::UserName  obviates the need to do a platform check and to strip off the domain-name part on Windows, and also avoids the costly external-utility call (whoami) on Unix-like platforms (which, as an aside, would fail on device platforms such as Android). In short: Unless you explicitly need to handle platforms other than Windows and Unix-like ones (a WASM environment in a web browser is the only one I am aware of), there is no good reason to implement a function.
As an aside, re your function: There's never a need to use $(...) for capturing an external program's output - $value = whoami will do. It's best to avoid pseudo method syntax: Instead of New-Object SomeType(arg1, ...), use New-Object SomeType [-ArgumentList] arg1, ... The PowerShell-idiomatic way to refer to the last element of an array is [-1] ($parts[-1]). PowerShell's operators are case-insensitive by default; thus, -ieq is the same as -eq, and -ieq is rarely seen in practice; it exists for symmetry with the c-prefixed, case-sensitive variants such as -ceq.
0

$ENV:USERNAME

Does this work in Linux? I know it works in Windows PowerShell

EDIT:
or try this for Linux
$ENV:USER

This is said to work universally for both
[System.Environment]::UserName

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.