query user 指令無法在platform target爲x86時使用

近期做一個項目,需要獲取電腦當前的登錄用戶,網上查找資料,發現可以直接使用以下兩種方式:

  1. System.Environment.UserName(),
  2. WindowsIdentity.GetCurrent().Name

實際使用後發現這兩種方法都無法或者到當前登錄的用戶名,因爲我的軟件是運行在網絡service上的,這種情況下拿到的值如下:

  1. WindowsIdentity.GetCurrent().Name: NT AUTHORITY\NETWORK SERVICE
  2. System.Environment.UserName: MS12520(電腦的名字)

繼續查找相關資料,後來發現,有前輩用用查詢任務管理器裏面explorer.exe的方式來獲取用戶戶名:

string username = string.Empty;
var query = new ObjectQuery("SELECT * FROM Win32_Process WHERE Name = 'explorer.exe'");
var explorerProcesses = new ManagementObjectSearcher(query).Get();
foreach (ManagementObject mo in explorerProcesses)
{
	string[] ownerInfo = new string[2];
	mo.InvokeMethod("GetOwner", ownerInfo);
	username = string.Concat(ownerInfo[1], @"\", ownerInfo[0]);
}

但是這種方式有個問題,如果有用戶遠程連接到此電腦,將會有多個explorer.exe進程,這種方式只是按照順序拿了第一個用戶,並不是當前登錄的用戶。

繼續查詢,發現可以調用cmd.exe,使用 query user/quser 獲取用戶列表,獲取到狀態爲active的用戶。

簡化操作,將指令編寫爲bat/cmd腳本:

@echo off
rem query the active logged on users
for /f "tokens=1 delims= " %%i in ('query user ^| findstr /i "active"') do set user=%%i
set fullname=%USERDOMAIN%\%user:~0%
echo %fullname%

然後在程序中調用powershell執行此腳本,至於爲什麼不用cmd執行,嘗試過了,提示無法將“ quser”識別爲內部或外部命令,此處交代一下我的調試電腦和之後軟件的運行電腦都是64位電腦。

因爲時間比較緊張,所以直接切換爲powershell。後來實際運行發現,拿到的結果爲空,在網上查找了好多資料,也問了很多人,一直找不到原因。修改腳本,增加輸出打印,最後定位到大概率是query user沒有輸出,嘗試將這句指令替換爲 ipconfig /all 等其他指令,都是由輸出的,最後懷疑是platform的問題,將platform從x86修改爲Any CPU,同時需要勾掉 prefer 32 bit, 軟件運行成功。

注:大家看cmd執行那張圖,active那張圖用戶名前面有個三角號>,這個三角號在軟件運行在service上的時候是沒有的,所有user取了全部的內容,如果要直接在Windows下執行上面的腳本,需要去掉前面的三角號,修改如下:

set fullname=%USERDOMAIN%\%user:~1%

之後在網上查了一些資料,還是模模糊糊的,我猜測大概是x86的軟件在64位機上運行時是在WOW64中運行,這個環境不支持query user。查到一篇類似的文章貼在這裏,這篇文章應該可以結束cmd不能使用的原因了。

c# - 以32位運行時在System32中找不到C#文件

還有一個stack overflow 的提問,也貼在這裏:

Executing Quser windows command in C#; Returning result to String

如果大家看到這篇文章有什麼看法歡迎留言,大家一起討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章