为了账号安全,请及时绑定邮箱和手机立即绑定

Windows - 在运行测试之前检查计算机是否被锁定/注销

Windows - 在运行测试之前检查计算机是否被锁定/注销

C#
阿晨1998 2022-12-24 12:13:58
我有一套 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}
查看完整描述

1 回答

?
MMTTMM

TA贡献1869条经验 获得超4个赞

不幸的是,实际上并没有任何干净的方法来执行此操作,至少我找不到,除非您愿意使用类似query userwithPsExec的方法在每台 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。

然后它将信息组合成不同的情况:

  1. 如果 LogonUI 进程数大于或等于交互式桌面数,PC 将被注销或锁定。如果PC上有任何LogonSession(带explorer),则锁定,否则注销。

  2. 如果 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;

    }

}


查看完整回答
反对 回复 2022-12-24
  • 1 回答
  • 0 关注
  • 76 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信