Это похоже, но не на обман, этот вопрос - однако, где он искал информацию о ручном присоединении сервера к домену (и был правильно перенаправлен), я ищу помощь с некоторым кодом, который программно присоединяет машину к домену.
Сценарий заключается в том, что у нас есть служба запуска, которая создает экземпляры виртуальных машин Amazon EC2 Server2008R1, при необходимости передавая имя машины через поток пользовательских данных. В наши образы встроен процесс, который проверяет пользовательские данные на наличие имени при загрузке. Если его нет, виртуальная машина остается за пределами нашего облачного домена, но если имя присутствует, то машина переименовывается, как указано, и автоматически присоединяется к домен.
Вот в чем проблема - если я запускаю этот процесс вручную в любое время после запуска экземпляра, он работает точно так, как описано; имя машины изменено, и виртуальная машина присоединена к домену (мы принудительно перезапускаем, чтобы это произошло).
Однако при запуске в качестве запланированной задачи (запускаемой при запуске) переименование машины происходит, как и ожидалось, но последующий вызов JoinDomainOrWorkgroup (см. ниже) выбирает старое рандомизированное имя машины, присвоенное виртуальной машине EC2, вместо нового имени только что был назначен.
Это приводит к коду возврата WMI 8525, мы получаем отсоединенную запись с неверным именем в репозитории AD (с этим рандомизированным именем), и машина не присоединена к домену. Затем виртуальная машина перезапускается, и второй проход через процесс запуска (ненормально запущенный, потому что в User-Data есть содержимое, но машина еще не находится в домене) выполняет все те же шаги и завершается успешно.
Похоже, что имя машины задано в первом проходе, но не «доработано», и JoinDomainOrWorkgroup по-прежнему видит исходное имя. При втором проходе имя машины уже задано правильно, поэтому JoinDomainOrWorkgroup работает как положено. Я думаю, что суть проблемы заключается в том, почему процесс ведет себя таким образом во время запуска, но отлично работает при ручном запуске на уже запущенной виртуальной машине.
Я попытался вставить задержку между шагами переименования и соединения на случай, если вызов 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, и это в значительной степени взято из примеров, которые я нашел в Интернете; если есть более умный/аккуратный способ сделать это, то обязательно продемонстрируйте. Если вы можете решить проблему в то же время, бонусные баллы!
SetMachineNameработает, но имя не меняется мгновенно -ipconfigпо-прежнему показывает старое имя, а просмотр свойств системы показывает старое имя, за которым следует (изменится на XXXXXXX после перезапуска). ЕслиSetDomainMembershipполучает путь управления к System.Environment.MachineName, это по-прежнему старое и неверное имя (что приводит к повреждению записи AD и неудачному соединению). Если вместо этого я передам новое имя в качестве параметра, вызов WMI завершится ошибкой с исключением «Не найдено», предположительно потому, что еще нет машины с этим новым именем. - person Eight-Bit Guru   schedule 16.11.2010