繁体   English   中英

C#:以编程方式检测 Windows Server 已启动

[英]C#: Programmatically Detect Windows Server Has Booted

我正在使用 C# 进行自动化过程,该过程将远程重新启动 Windows (2008/2012/2016) 服务器,我需要等到该服务器重新联机才能继续。

我知道“返回在线”可能不明确,因此根据我的要求,我需要服务器返回 Ctrl-Alt-Del 屏幕。 这样做的原因是在继续之前让服务器处于一致状态。 根据我的经验,有几个因素可能会阻止服务器到达此屏幕,例如安装 Windows 更新卡在重启周期或卡在“等待本地会话管理器”等。

我花了几天时间研究这个无济于事:

  • 服务器显然在它可用之前就开始响应 ping 请求
  • 系统启动时间发生在服务器达到所需状态之前
  • 任何指示系统已启动的事件都会在所需状态之前记录下来
  • 我不能简单地轮询基本服务 - 当 Windows 在登录之前应用计算机更新时,这些服务可能已经启动。 此外,有时服务器会在此阶段安装更新时自行重启,这可能会导致误报。
  • 轮询 CPU 活动也可能产生误报或引入延迟

无论如何检测Windows服务器已完成启动并且可用于交互式登录?

听起来你已经涵盖了我所知道的大多数可能的方式。 这让我恢复到蛮力的想法。 我很好奇你在做什么,你不能在盒子上安装 Windows 服务(或者因为数量不是很可行)

首先只是尝试远程登录或其他什么,并有一些方法来测试它是否失败,等待 1 分钟,再试一次。 但似乎这可能会以某种方式对您造成副作用?

我对不影响状态的蛮力方法的想法:

  • 每 1-5 秒 ping 一次
  • 一旦它开始响应
  • 等待 5 或 10 甚至 15 分钟,同时仍然 ping 它
  • 如果 ping 失败,则重置该计时器(Windows 更新重启情况)
  • 然后非常自信你处于正确的状态。

可能有数千台服务器,我无法想象每个 15 分钟会是什么大不了的事,尤其是如果它足够一致以能够大批量运行

所以我已经能够通过使用一种看起来在我的测试环境中工作的hacky方法来实现这一点。

请注意,el.Current.Name 属性将等同于 Ctrl-Alt-Del 文本,因此在 2008R2 上,这是“按 CTRL-ALT-DEL 登录”和“按 CTRL-ALT-DEL 登录”。 在 2012R2

我构建了一个使用 UI 自动化的 C# 控制台应用程序:

using System;
using System.Windows.Automation;

namespace WorkstationLocked
{
    class Program
    {
        static void Main()
        {
            AutomationElement el = AutomationUI.FindElementFromAutomationID("LockedMessage");

            if (el !=null)
            {
                Console.WriteLine(el.Current.Name);
            }
        }
    }
    class AutomationUI
    {
        public static AutomationElement FindElementFromAutomationID(string automationID)
        {
            string className = "AUTHUI.DLL: LogonUI Logon Window";

            PropertyCondition condition = new PropertyCondition(AutomationElement.ClassNameProperty, className);
            AutomationElement logonui = AutomationElement.RootElement.FindFirst(TreeScope.Children, condition);

            if (logonui != null)
            {
                condition = new PropertyCondition(AutomationElement.AutomationIdProperty, automationID);
                return logonui.FindFirst(TreeScope.Descendants, condition);
            }
            else
            {
                return null;
            }

        }
    }
}

然后我可以通过 PsExec 执行这个控制台应用程序,但是,因为这需要在 winlogon 桌面中启动,这只能通过在本地系统下运行来完成,所以 PsExec 被调用了两次。 例如:

psexec.exe \\ServerA -s -d C:\PsTools\PsExec.exe -accepteula -d -x C:\Utils\WorkstationLocked.exe

这是一项目前正在进行的工作,因为我无法将命令的输出传递给调用进程,因此我可能只想填充一个注册表值或写入一个可以随后进行查询的文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM