以编程方式将Windows计算机加入AD域

问题描述 投票:7回答:2

这类似于this question,但并非其伪装-但是,它在寻求有关将服务器手动连接到域(并已正确重定向)的信息,我正在寻找一些以编程方式连接机器的代码的帮助到一个域。

该情况是我们有一个启动器服务,该服务可实例化Amazon EC2 Server2008R1 VM,可以选择通过用户数据流传递计算机名称。在我们的映像中包含一个进程,该进程在启动时检查用户数据的名称-如果不存在该名称,则VM仍在我们的Cloud域之外,但是如果存在该名称,则将计算机重命名为指定名称并自动加入域。

这里是问题-如果我在实例启动后的任何时间手动运行此过程,则该过程将完全按照说明进行;机器名称已更改,并且VM已加入域(我们强制重新启动以使这种情况发生)。

但是,当作为计划任务运行(在启动时触发)时,计算机重命名会按预期进行,但随后对JoinDomainOrWorkgroup的调用(请参见下文)将使用由EC2代替VM分配给VM的旧的随机计算机名称。刚分配的新名称。

这将导致WMI返回代码为8525,我们在AD存储库中获得了一个断开连接的错误命名条目(具有该随机名称),并且该计算机未加入域。然后,VM重新启动,并且第二次执行启动过程(由于User-Data中包含内容,但计算机尚未在域中而异常触发),将执行所有相同的步骤并成功执行。

看起来机器名称是在第一遍中设置的,但未“完成”,并且JoinDomainOrWorkgroup仍然看到原始名称。在第二遍,计算机名称已经正确设置,因此JoinDomainOrWorkgroup可以按预期工作。我认为问题出在这个问题上,这就是为什么该过程在启动期间会以这种方式运行,而在已启动的VM上手动运行时却能完美运行的原因。

我已经尝试在重命名和加入步骤之间插入一个延迟,以防在重命名在幕后完成之前对JoinDomainOrWorkgroup的调用发生了,但这并没有帮助-我真的没想到它会,因为手动运行时整个过程可以完美运行。因此,这可能是启动期间机器状态的细微差异与代码中一些愚蠢的组合。

也许不建议在System.Environment.MachineName方法中使用SetDomainMembership?但是,即使我像SetMachineName一样将新名称作为字符串传递,它也会失败。所以我很困惑。

这里是重命名机器的WMI代码:

/// <summary>
/// Set Machine Name
/// </summary>
public static bool SetMachineName(string newName)
{
  _lh.Log(LogHandler.LogType.Debug, string.Format("Setting Machine Name to '{0}'...", newName));

  // Invoke WMI to populate the machine name
  using (ManagementObject wmiObject = new ManagementObject(new ManagementPath("Win32_ComputerSystem.Name='" + System.Environment.MachineName + "'")))
  {
    ManagementBaseObject inputArgs = wmiObject.GetMethodParameters("Rename");
    inputArgs["Name"] = newName;

    // Set the name
    ManagementBaseObject outParams = wmiObject.InvokeMethod("Rename", inputArgs, null);

    // Weird WMI shennanigans to get a return code (is there no better way to do this??)
    uint ret = (uint)(outParams.Properties["ReturnValue"].Value);
    if (ret == 0)
    {
      // It worked
      return true;
    }
    else
    {
      // It didn't work
      _lh.Log(LogHandler.LogType.Fatal, string.Format("Unable to change Machine Name from '{0}' to '{1}'", System.Environment.MachineName, newName));
      return false;
    }
  }
}

这是将其加入域的WMI代码:

/// <summary>
/// Set domain membership
/// </summary>
public static bool SetDomainMembership()
{
  _lh.Log(LogHandler.LogType.Debug, string.Format("Setting domain membership of '{0}' to '{1}'...", System.Environment.MachineName, _targetDomain));

  // Invoke WMI to join the domain
  using (ManagementObject wmiObject = new ManagementObject(new ManagementPath("Win32_ComputerSystem.Name='" + System.Environment.MachineName + "'")))
  {
    try
    {
      // Obtain in-parameters for the method
      ManagementBaseObject inParams = wmiObject.GetMethodParameters("JoinDomainOrWorkgroup");

      inParams["Name"] = "*****";
      inParams["Password"] = "*****";
      inParams["UserName"] = "*****";
      inParams["FJoinOptions"] = 3; // Magic number: 3 = join to domain and create computer account

      // Execute the method and obtain the return values.
      ManagementBaseObject outParams = wmiObject.InvokeMethod("JoinDomainOrWorkgroup", inParams, null);
      _lh.Log(LogHandler.LogType.Debug, string.Format("JoinDomainOrWorkgroup return code: '{0}'", outParams["ReturnValue"]));

      // Did it work?  ** disabled so we restart later even if it fails
      //uint ret = (uint)(outParams.Properties["ReturnValue"].Value);
      //if (ret != 0)
      //{
      //  // Nope
      //  _lh.Log(LogHandler.LogType.Fatal, string.Format("JoinDomainOrWorkgroup failed with return code: '{0}'", outParams["ReturnValue"]));
      //  return false;
      //}

      return true;
    }
    catch (ManagementException e)
    {
      // It didn't work
      _lh.Log(LogHandler.LogType.Fatal, string.Format("Unable to join domain '{0}'", _targetDomain), e);
      return false;
    }
  }
}

抱歉,如果这段代码看起来愚蠢,我是WMI的新手,而这很大程度上取决于我在互联网上发现的示例;如果有更聪明/更整洁的方式来执行此操作,则请务必进行演示。如果您可以同时解决问题,则可以加分!

这类似于但不是该问题的重复,但是,在这里它寻求有关手动将服务器加入域(并已正确重定向)的信息,我正在寻找一些代码的帮助...

c# dns wmi amazon-ec2
2个回答
8
投票

确定,就在这里。

首先,系统属性中字段的顺序有点误导-您首先看到计算机名称,然后在下面看到域/工作组。这下意识地影响了我的思想,这意味着我的代码通过尝试先设置名称,然后将计算机加入域来复制了该顺序。尽管这在某些情况下确实可行,但并不始终如一或可靠。因此,这里最大的教训是...


0
投票

这些年来如果有人需要,请稍加更新。

© www.soinside.com 2019 - 2024. All rights reserved.