1 回答

TA貢獻1869條經驗 獲得超4個贊
不幸的是,實際上并沒有任何干凈的方法來執行此操作,至少我找不到,除非您愿意使用類似query user
withPsExec
的方法在每臺 PC 上將其作為子進程遠程執行,然后解析結果。即使那樣,您也無法直接獲得有關鎖定狀態的答案,您將不得不按空閑時間進行處理,因為當沒有人使用計算機時,狀態會將其中一個用戶顯示為活動狀態。
然后是多個用戶登錄計算機的問題,使用 Windows 7 或更高版本中的切換用戶功能。在我的環境中,一臺 PC 可能有 3 或 4 個后臺用戶和一個控制臺用戶。在某些情況下,PC 由 RDP 用戶使用。事實證明,當您通過 RDP 連接到計算機然后登錄到控制臺或執行相反操作時,會出現一種特殊情況,因為在這些情況下 LogonSession LogonType 不會更新。不幸的是,也有可能捕捉到用戶剛剛登錄計算機,在這種情況下,我的函數將錯誤地指出計算機未在使用中。
在我的 PC 和網絡上,如果 PC 打開,此函數運行大約需要 0.2 秒。在某些 PC 上,它可能需要更長的時間(最多 20 秒),因為它會在 PC 上加載 perfmon 提供程序。如果 PC 關閉,超時時間會很長,如果可能的話,我建議先進行 ping 檢查。
基本上,該函數使用 WMI 獲取 LogonSession 和交互式桌面信息,并Process
獲取 LogonUI 和資源管理器進程。由于 LogonSession 返回已注銷的舊會話,以及 UAC 管理程序和其他 (Windows 10) 后臺進程 (DWM/UMFD) 的會話,因此我們只計算具有explorer.exe
進程(桌面)的 LogonSession。
然后它將信息組合成不同的情況:
如果 LogonUI 進程數大于或等于交互式桌面數,PC 將被注銷或鎖定。如果PC上有任何LogonSession(帶explorer),則鎖定,否則注銷。
如果 LogonUI 進程數少于交互式桌面數,則 PC 正在使用中。
這是代碼:
enum PCUserStatuses {
Locked, // all users are locked
LoggedOff, // No users are logged in
InUse, // A user is using this computer
Unknown // unable to connect to computer / other error
}
PCUserStatuses GetPCUserStatus(string machineName) {
try {
var scope = GetManagementScope(machineName);
scope.Connect();
var explorerProcesses = Process.GetProcessesByName("explorer", machineName)
.Select(p => p.Id.ToString())
.ToHashSet();
var REprocessid = new Regex(@"(?<=Handle="").*?(?="")", RegexOptions.Compiled);
var numberOfLogonSessionsWithExplorer = new ManagementObjectSearcher(scope, new SelectQuery("SELECT * FROM Win32_SessionProcess")).Get()
.Cast<ManagementObject>()
.Where(mo => explorerProcesses.Contains(REprocessid.Match(mo["Dependent"].ToString()).Value))
.Select(mo => mo["Antecedent"].ToString())
.Distinct()
.Count();
var numberOfUserDesktops = new ManagementObjectSearcher(scope, new SelectQuery("select * from win32_Perfrawdata_TermService_TerminalServicesSession")).Get().Count - 1; // don't count Service desktop
var numberOflogonUIProcesses = Process.GetProcessesByName("LogonUI", machineName).Length;
if (numberOflogonUIProcesses >= numberOfUserDesktops) {
if (numberOfLogonSessionsWithExplorer > 0)
return PCUserStatuses.Locked;
else
return PCUserStatuses.LoggedOff;
}
else
return PCUserStatuses.InUse;
}
catch {
return PCUserStatuses.Unknown;
}
}
- 1 回答
- 0 關注
- 104 瀏覽
添加回答
舉報