使用動態 PowerShell 獲取當前用戶

當您在使用Windows時,可能需要查詢目前有哪些使用者帳戶登入到一台電腦上。幸運的是,您可以使用PowerShell來獲取本機或遠端電腦上的當前使用者。

在您的Active Directory中是否存在被入侵的密碼?使用Specops Password Auditor Free來查明。

在這個教程中,您將學到使用PowerShell在電腦上獲取當前使用者的幾種方法。您將學到的方法包括本機命令、.NET類別以及Windows管理儀器(WMI)的特定cmdlet。

準備好查明誰正在潛伏在您的電腦上嗎?讓我們開始吧!

先決條件

在這個教程中,您最好是通過跟隨示例來學習。為此,您需要一台運行任何現代版本Windows(如Windows 10、Windows Server 2012或更高版本)的電腦。

本教程將使用一台運行Windows Server 2019,名為DC1的電腦。

為什麼使用PowerShell來獲取當前登入電腦的使用者?

确實,有多種方法可以在不使用 PowerShell 的情況下獲取當前用戶登錄到計算機的方式。畢竟,在 PowerShell 出現之前,系統管理員必須有一種方法來實現這一點,對吧?如果是這樣,為什麼要使用 PowerShell?

在 PowerShell 中執行相同任務的好處在於將結果視為可以操作的對象。例如,如果運行一個提示用戶輸入憑據的腳本,PowerShell 可以以編程方式填充用戶名,而您只需要手動輸入密碼。

另一個現實世界的例子是將當前登錄到服務器的用戶列表導出到文件。這是通過使用 PowerShell 獲取當前用戶,然後將結果導出到CSVHTMLXML文件。之後,各種自動化工作流程可以使用此輸出。

使用 PowerShell 獲取當前用戶可能有成千上萬個原因,但最終目標歸結為您的需求。本教程將教您實現該目標的不同方法。

查詢 Win32_ComputerSystem 類

讓我們從 PowerShell 原生的 cmdlet 開始,名為 Get-WMIObject Get-CimInstance。這些 cmdlet 允許您使用 Windows Management Instrumentation (WMI) 在本地或遠程計算機上查詢信息,包括當前登錄的使用者。

Get-WMIObject 是舊版(已棄用)的 cmdlet,僅適用於 Windows PowerShell 5.1。相反,Get-CIMInstance 是更新、更安全的 cmdlet,可用於 最新的 PowerShell 版本

欲了解更多,請參閱 Get-CIMInstance Vs. Get-WMIObject: What’s The Difference?

使用 PowerShell 获取当前用户,调用针对 Win32_ComputerSystem 类 的 cmdlet 之一。Win32_ComputerSystem 类包含各种属性,包括 Username 属性。要执行此操作,请打开 PowerShell 窗口并运行以下命令。

# 使用 Get-WMIObject cmdlet 并仅返回 Username 属性
(Get-WMIObject -ClassName Win32_ComputerSystem).Username

# 使用 Get-CimInstance cmdlet 并仅返回 Username 属性
(Get-CimInstance -ClassName Win32_ComputerSystem).Username

注意:查询 Win32_ComputerSystem 类 仅返回直接登录到计算机的用户的用户名(控制台会话)。如果用户远程登录(例如,远程桌面),用户名将为空。

两个命令返回相同的结果,如下所示。如果当前用户是域用户账户,则命令将返回域和用户名(domain\username)。但对于本地用户账户,输出将是 computer\username

Querying WMI in PowerShell to Get Current Users

Get-WMIObjectGet-CimInstance 都有一個名為 -computerName 的參數,它接受計算機的名稱來查詢。使用這個參數意味著您可以從網絡中的遠程計算機查詢相同的信息。

但如果您只需要獲取不帶域的用戶名,一種解決方案是使用 split() 方法 來分割輸出。為此,在 PowerShell 中運行下面的命令。

# 下面的命令將使用反斜杠 '\' 字符將用戶名屬性分割成兩部分。
# 尾部的 [1] 部分告訴命令僅返回索引 1 的結果。
# 索引從 0 開始,這意味著指定索引 1 將顯示第二個位置的結果。
((Get-WMIObject -ClassName Win32_ComputerSystem).Username).Split('\')[1]

因此,PowerShell僅返回用戶部分,就像下面的屏幕截圖一樣。

Splitting the username property

讀取 Windows 環境變量

使用PowerShell另一种获取计算机上当前用户的方法是从环境变量中检索值。环境变量代表操作系统数据,包括当前用户的用户名等。

有三种与环境变量交互的方式。无论选择哪种方式,都会返回相同的结果。

Env PowerShell驱动器

PowerShell会缓存环境变量,并通过一个称为Env:PowerShell驱动器(PSDrive)将其提供出来。PSDrive是数据位置,您可以像访问计算机上的驱动器(例如C:)一样访问它们,但仅在PowerShell内部可访问。

PowerShell 在打開 PowerShell 會話時會自動建立 Env: 磁碟。而且因為 Env: 是一個磁碟,您可以通過調用 Get-ChildItem cmdlet 來獲取其內容,類似於列出檔案系統磁碟或文件夾的內容。

在 PowerShell 中使用 Env: 磁碟,通過運行下面的命令獲取當前用戶。

Get-ChildItem Env:\USERNAME

下面的截圖顯示了預期的結果。如您所見,該命令返回了 USERNAME 項目及其相應的值,即當前登錄的用戶。

Getting the Env:\USERNAME item

為僅返回用戶名值,請按照下面所示修改命令並在 PowerShell 中重新運行它。

(Get-ChildItem Env:\USERNAME).Value

如您所見,該命令僅以字串形式返回用戶名值。

Getting the Env:\USERNAME value

環境變量 $env

除了將環境變量作為 PSDrive 存取,將其視為磁碟中的文件外,另一種方法是將 Env 磁碟作為變量進行存取。這意味著您可以使用以下語法引用環境變量。

# 美元符號表示變數
# env 是 Env 驅動器
# <variable> 是您想要獲取的變數名稱
$env:<variable>

根據上述語法,在 PowerShell 中運行以下命令以獲取當前用戶。

$env:username

正如下面的截圖所示,該命令返回用戶名值。

Getting the username variable value

.NET Environment 類

PowerShell 是一種面向對象的語言和 shell。實際上,在 PowerShell 中進行的所有工作都是對象。當您運行命令時,輸出是一個對象。如果您聲明了一個變數,該變數本身就是一個對象。您明白了。

這些對象有一種結構,定義了它們代表的數據類型,類似於藍圖。而這些藍圖稱為 .NET 類 或簡單地稱為類。

关于环境变量,与之相关的类是 Environment 类。那么在 PowerShell 中如何使用 Environment 类来获取当前用户呢?

就像 $env 变量一样,Environment 类有一个 Username 属性,其值为当前用户的用户名。要获取用户名属性的值,请在 PowerShell 中运行以下命令。

[System.Environment]::UserName
Getting the environment username property value

除了 Username 属性之外,Environment 类还有一个获取环境变量值的方法。该方法的名称是 GetEnvironmentVariable

要使用此方法获取当前用户,请运行以下命令。

[System.Environment]::GetEnvironmentVariable('username')
Getting the environment variable value

使用 .NET WindowsIdentity 类

WindowsIdentity 類別是另一個您可以在 PowerShell 中調用的 .NET 類別,以獲取當前使用者。這個類別具有一個名為 GetCurrentName 的方法,該方法返回表示當前 Windows 使用者的物件。

要獲取當前使用者的詳細資訊,請執行下面的命令。

[System.Security.Principal.WindowsIdentity]::GetCurrent()

如下所示,該命令返回當前使用者物件的屬性,包括 Name 屬性。 Name 屬性值的格式遵循 domain\user 慣例。

Getting the current Windows user

要僅返回使用者名稱部分,請修改上一個命令以僅選擇 Name 屬性,並應用字串拆分技術。 要這樣做,請複製下面的命令並在 PowerShell 中運行它。

([System.Security.Principal.WindowsIdentity]::GetCurrent().Name).Split('\')[1]
Returning only the username part

使用 whoami 命令

另一個方便的命令,可以快速獲取當前使用者的是 whoami 命令。 這個命令是一個可執行文件,您可以在 %WINDIR%\System32 文件夾中找到,文件名為 whoami.exe

要獲取當前使用者的使用者名稱,請執行下面的命令。

whoami

然後,該命令以 domain username 格式返回結果,例如下面的截圖。

Getting the username using whoami

要獲取不帶域名的用戶名,請應用您在本教程中學到的字符串分割技術,運行下面的命令。

(whoami).Split('\')[1]
Getting the username without the domain

whoami 命令還可以返回當前用戶的完全限定的區分名稱(FQDN)和用戶主要名稱(UPN)。如果您打算運行一個檢索當前用戶身份的腳本,這個命令輸出可能會很有幫助,超出用戶名。

在 PowerShell 中運行下面的命令以獲取當前用戶的 FQDN 和 UPN。

# 獲取當前用戶的 FQDN
whoami /fqdn

# 獲取當前用戶的 UPN
whoami /upn
Getting the current user’s FQDN and UPN

注意:只有當前登錄的用戶是域用戶時,FQDN 和 UPN 值才可用。如果您嘗試為本地用戶獲取這些值,該命令將返回錯誤,如下所示。

Error getting the UPN and FQDN of a non-domain user account

使用 query 命令

如果您是系統管理員或域用戶,很有可能您曾經通過遠程桌面協議(RDP)登錄到遠程計算機,至少有一次,也許是為了管理資源或使用應用程序。無論出於什麼原因,您都想知道當前誰正在登錄並使用系統資源。

幸運的是,Windows有一個內置的命令行工具,名為query,可以列出計算機上所有當前已登錄的用戶。該命令還顯示用戶是通過遠程桌面會話還是本地登錄到計算機。

與獲取已登錄用戶相關的query命令有兩個相關的參數; sessionusersession參數列出計算機會話,而user參數列出用戶及其會話。

query session命令有一個別名,稱為qwinsta,而query user的命令別名為quser

例如,運行下面的命令來列出DC1上的會話。

# query sessions on DC1
qwinsta /server:dc1

以下是命令输出的屏幕截图。在这个例子中,有两个用户登录到了DC1计算机——一个在控制台会话中,另一个通过RDP。正如你所看到的,qwinsta返回所有会话,甚至包括非用户会话。

Querying sessions

如果你单独运行qwinstaquser而不使用/server:<computer>参数,任一命令都将默认查询本地计算机。

接下来,为了列出所有存在登录会话的用户,请运行下面的user命令。

# 查询DC1上的用户
quser /server:dc1

运行命令后,你会立即注意到quser返回的会话和用户与qwinsta命令相似。但这次,没有空白会话。

还有两列额外的信息:IDLE TIME,显示用户的空闲时间,和LOGON TIME,显示用户的登录时间戳。

Querying users

最后,比较qwinstaquser的结果,quser是PowerShell中获取当前用户的更合适的命令。

在你的Active Directory中是否存在被 compromise 的密码?使用Specops Password Auditor Free来查明。

结论

當在PowerShell中獲取當前登錄用戶時,有很多方法,最佳方法取決於您打算獲得的結果以及您將如何使用它。

使用本機的WMI相關cmdlet和query命令可讓您獲取本地或遠程計算機上的已登錄用戶。使用.NET類和環境變數可快速獲取相同的結果,但僅限於本地計算機。

無論您計劃運行腳本還是手動在屏幕上顯示結果,都有一種方法可以滿足您使用PowerShell獲取當前用戶的要求。接下來呢?也許學習如何解析query命令的結果,並通過編寫帶有RegEx的函數將它們轉換為PowerShell對象

Source:
https://adamtheautomator.com/powershell-get-current-user/