A Cross-Platform Technique for Obtaining Username with PowerShell Core
23 Sep 2018 · Comments: · Tags: PowerShellProblem
While developing a PowerShell Core script I required a means of obtaining the username of the account under which it was run. Since the script was intended to be used on both Windows and GNU/Linux I sought a technique that would work on both platforms.
NB: At the time of writing the script I was using PowerShell 6.1.0 on Windows 10 and Ubuntu Server 16.04 LTS.
Investigation
My initial thought was to use an environment variable within PowerShell’s Env:
drive but I soon discovered that the variable names differed between Windows
($env:USERNAME
) and Ubuntu ($env:USER
). Upon examining the PowerShell
Core source code it became evident that PowerShell itself places relatively few
items into the Env:
drive and that its mostly comprised of platform specific
variables, hence the inconsistency in naming between Windows and Ubuntu
(behind the scenes, PowerShell does this by calling the .Net method Environment.GetEnvironmentVariables
).
I briefly considered writing a function to extract the username from the
appropriate environment variable based on whether the platform was Windows or
GNU/Linux but this became less attractive when I realised that if the script
was run as a cron job on Ubuntu it did not have access to $env:USER
(this is
a result of cron’s design), so such a function would have to take that into
consideration.
whoami
Workaround - In recent years Windows has shipped with a whoami
binary, whereas in older
versions it was typically available as part of the operating system’s resource
kit. On GNU/Linux systems it is part of the GNU coreutils.
Whilst this delivered the desired result (at least on Windows 10 and Ubuntu) I disliked the dependency on the presence of a third party binary, hence I considered this to be a workaround rather than a solution.
Solution
I proceeded to open an issue
on the PowerShell Core Github repository where I was advised to use
[Environment]::UserName
. This proved to work well and was the solution I opted
to use.
Further Research
I was curious as to how PowerShell core obtained username for use in transcript file prologues, EG:
Upon inspecting the PowerShell Core Github repository I
found that it also used the UserName property of the .Net Environment class.
Start-Transcript
(PowerShell/src/Microsoft.PowerShell.ConsoleHost/host/msh/StartTranscriptCmdlet.cs)
calls StartTranscribing
(PowerShell/src/System.Management.Automation/namespaces/EnvironmentProvider.cs),
which in turn calls LogTranscriptHeader
which
populates the username
with Environment.UserDomainName + "\\" + Environment.UserName
unless PowerShell
remoting is involved in which case the username is obtained from a Powershell
automatic variable $PSSenderInfo.UserInfo.Identity.Name
.
Comments