Это похоже на, но не обман, this question - однако, когда он искал информацию о ручном подключении сервера к домену (и был правильно перенаправлен), я ищу помощь с некоторыми код, который программно соединяет машину с доменом.Программно подключиться к Windows-машине к домену AD
Сценарий заключается в том, что у нас есть служба запуска, которая запускает виртуальные машины Amazon EC2 Server2008R1, опционально передавая имя машины через поток User-Data. Процесс обрабатывается нашими изображениями, которые проверяют User-Data для имени при загрузке. Если ни один не присутствует, VM остается за пределами нашего облачного домена, но если имя присутствует, то машина переименовывается как заданная и автоматически присоединяется к домена.
В этом случае проблема - если я запускаю этот процесс вручную в любое время после запуска экземпляра, он работает точно так, как описано; имя машины изменяется, а виртуальная машина присоединена к домену (мы вынуждаем перезапуск, чтобы это произошло).
Однако при запуске в качестве запланированной задачи (запускается при запуске) переименование машины происходит так, как ожидалось, но последующий вызов JoinDomainOrWorkgroup
(см. Ниже) подбирает старое рандомизированное имя машины, присвоенное VM EC2 вместо новое имя, которое оно только что назначено.
Это приводит к обратному коду WMI . Мы получаем несвязанную запись с неправильным названием в репозитории 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;
}
}
}
Извинения, если этот код выглядит ум numbingly глупо - я «Новое для WMI», и это в значительной степени связано с примерами, которые я нашел на веб-сайтах; если есть более умный/более быстрый способ сделать это, то непременно продемонстрируйте. Если вы можете вылечить проблему в одно и то же время, бонусные баллы!
Дополнительная информация: вызов 'SetMachineName' работает, но имя не меняется мгновенно -' ipconfig' все еще показывает старое название, и, глядя на свойствах системы показывает старое название, за которой следует «(изменится до XXXXXXX после перезапуска) ". Если 'SetDomainMembership' получает путь управления к System.Environment.MachineName, это по-прежнему старое имя и неверно (что приводит к сломанной записи AD и неудачному соединению). Если я вместо этого передаю новое имя в качестве параметра, вызов WMI завершится неудачей с исключением «Not Found», по-видимому, потому, что еще не установлена машина с этим новым именем. –