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 关注
- 76 浏览
添加回答
举报