1 回答

TA貢獻1869條經(jīng)驗 獲得超4個贊
不幸的是,實際上并沒有任何干凈的方法來執(zhí)行此操作,至少我找不到,除非您愿意使用類似query user
withPsExec
的方法在每臺 PC 上將其作為子進程遠程執(zhí)行,然后解析結(jié)果。即使那樣,您也無法直接獲得有關(guān)鎖定狀態(tài)的答案,您將不得不按空閑時間進行處理,因為當(dāng)沒有人使用計算機時,狀態(tài)會將其中一個用戶顯示為活動狀態(tài)。
然后是多個用戶登錄計算機的問題,使用 Windows 7 或更高版本中的切換用戶功能。在我的環(huán)境中,一臺 PC 可能有 3 或 4 個后臺用戶和一個控制臺用戶。在某些情況下,PC 由 RDP 用戶使用。事實證明,當(dāng)您通過 RDP 連接到計算機然后登錄到控制臺或執(zhí)行相反操作時,會出現(xiàn)一種特殊情況,因為在這些情況下 LogonSession LogonType 不會更新。不幸的是,也有可能捕捉到用戶剛剛登錄計算機,在這種情況下,我的函數(shù)將錯誤地指出計算機未在使用中。
在我的 PC 和網(wǎng)絡(luò)上,如果 PC 打開,此函數(shù)運行大約需要 0.2 秒。在某些 PC 上,它可能需要更長的時間(最多 20 秒),因為它會在 PC 上加載 perfmon 提供程序。如果 PC 關(guān)閉,超時時間會很長,如果可能的話,我建議先進行 ping 檢查。
基本上,該函數(shù)使用 WMI 獲取 LogonSession 和交互式桌面信息,并Process
獲取 LogonUI 和資源管理器進程。由于 LogonSession 返回已注銷的舊會話,以及 UAC 管理程序和其他 (Windows 10) 后臺進程 (DWM/UMFD) 的會話,因此我們只計算具有explorer.exe
進程(桌面)的 LogonSession。
然后它將信息組合成不同的情況:
如果 LogonUI 進程數(shù)大于或等于交互式桌面數(shù),PC 將被注銷或鎖定。如果PC上有任何LogonSession(帶explorer),則鎖定,否則注銷。
如果 LogonUI 進程數(shù)少于交互式桌面數(shù),則 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 關(guān)注
- 101 瀏覽
添加回答
舉報