我有一套UI测试,可以根据情况在本地/远程运行。有时,只要有重要更新要应用,远程计算机就会自动重新启动。这会导致所有测试超时,因为运行它们的远程计算机被锁定,并且无法再访问GUI。
我想知道如何快速检查计算机是否被锁定,这样我可以快速通过测试并记录它们是否处于脱机状态。
我在网上找到了该解决方案,但它似乎更适合开发而不是测试。
https://bytes.com/topic/net/answers/770957-get-computer-state-locked-stand-c
真的只是想要一种干净的方法来检查当前计算机是否已使用C#库锁定,然后将其放入类似下面的方法中。
public bool IsWindowsLocked(){
// Check if the current machine is in a locked state
}
答案 0 :(得分:2)
不幸的是,实际上并没有任何干净的方法可以做到这一点,至少我找不到,除非您愿意将query user
与PsExec
一起使用以在每台PC上远程执行它作为子过程,然后解析结果。即使这样,您也无法直接获得有关锁定状态的答案,您还必须等待空闲时间,因为当没有人使用计算机时,状态会显示其中一个用户为活动用户。
然后,存在使用Windows 7或更高版本中的“切换用户”功能在计算机上登录多个用户的问题。在我的环境中,一台PC可能有3或4个后台用户和一个控制台用户。在某些情况下,RDP用户使用PC。事实证明,当您将RDP连接到计算机,然后再登录到控制台或执行相反的操作时,是一种特殊情况,因为在这些情况下,LogonSession LogonType不会更新。不幸的是,也有可能抓住刚登录计算机的用户,在这种情况下,我的功能将错误地指出计算机未使用。
在我的PC和网络上,如果PC开启,则此功能大约需要运行0.2秒。在某些PC上,可能需要更长的时间(最多20秒),因为它会在PC上加载perfmon提供程序。如果PC关闭,则超时时间很长,如果有可能,我建议您先执行ping检查。
该函数基本上使用WMI来获取LogonSession和Interactive Desktops信息,并使用Process
来获取LogonUI和资源管理器进程。由于LogonSession返回已注销的旧会话以及UAC Admin程序和其他(Windows 10)后台进程(DWM / UMFD)的会话,因此,我们仅计算具有explorer.exe
进程(桌面)的LogonSessions。
然后将信息组合成不同的情况:
如果LogonUI进程数大于或等于交互式桌面数,则PC已注销或已锁定。如果PC上有任何LogonSession(带有资源管理器),它将被锁定,否则将被注销。
如果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;
}
}