Dies ist ähnlich, aber nicht ein Betrüger von, this question - jedoch, wo es Informationen über die manuelle Beitritt zu einem Server zu einer Domäne gesucht (und wurde zu Recht umgeleitet) Ich suche Hilfe mit einigen Code, der eine Maschine programmatisch einer Domäne hinzufügt.Programmatisch beitreten Windows-Maschine zu AD-Domäne
Das Szenario besteht darin, dass wir einen Launcher-Dienst haben, der Amazon EC2 Server2008R1-VMs instanziiert und optional einen Computernamen über den Benutzerdatenstrom weiterleitet. Ein Prozess wird in unsere Bilder eingebettet, der Benutzerdaten nach einem Namen beim Booten überprüft - Wenn keiner vorhanden ist, bleibt die VM außerhalb unserer Cloud-Domäne, aber wenn der Name vorhanden ist, wird der Computer wie angegeben umbenannt und automatisch verbunden die Domäne.
Hier ist das Problem - wenn ich diesen Prozess manuell jedes Mal nach dem Start der Instanz ausführen, funktioniert es genau wie beschrieben; Der Computername wird geändert und die VM wird mit der Domäne verbunden (wir erzwingen einen Neustart, um dies zu ermöglichen).
Beim Ausführen als geplante Task (ausgelöst beim Start) erfolgt die Maschinenumbenennung jedoch wie erwartet, aber der folgende Aufruf an JoinDomainOrWorkgroup
(siehe unten) übernimmt den alten, von VM2 über VM2 angegebenen, randomisierten Maschinennamen der neue Name wurde gerade vergeben.
Dies führt zu einem WMI-Rückkehrcode , wir erhalten einen getrennten Eintrag mit falschem Namen im AD-Repository (mit diesem randomisierten Namen) und der Computer ist nicht mit der Domäne verbunden. Die VM startet dann neu, und ein zweiter Durchlauf durch den Startprozess (abnormal ausgelöst, da Inhalt in Benutzerdaten vorhanden ist, aber die Maschine noch nicht in der Domäne ist) führt alle die gleichen Schritte aus und ist erfolgreich.
Es sieht so aus, als ob der Computername im ersten Durchlauf gesetzt, aber nicht 'finalisiert' ist, und JoinDomainOrWorkgroup
sieht immer noch den ursprünglichen Namen. Beim zweiten Durchlauf ist der Computername bereits richtig eingestellt, und JoinDomainOrWorkgroup
funktioniert wie erwartet. Ziemlich warum der Prozess so während des Starts funktioniert, aber funktioniert perfekt, wenn manuell auf einer bereits gestarteten VM ausgeführt wird, ist ich der Kern des Problems.
Ich habe versucht, eine Verzögerung zwischen den Umbenennen und Join Schritte für den Fall, dass der Anruf an JoinDomainOrWorkgroup
geschah, bevor das Umbenennen hinter den Kulissen abgeschlossen wurde, aber das hat nicht geholfen - und ich habe es nicht wirklich erwartet , da der ganze Prozess perfekt funktioniert, wenn er manuell ausgeführt wird. Es ist also wahrscheinlich eine Kombination aus einem subtilen Unterschied im Maschinenzustand während des Bootens und etwas albern im Code.
Vielleicht nicht mit System.Environment.MachineName
in der SetDomainMembership
Methode ist nicht ratsam? Aber es schlägt immer fehl, auch wenn ich den neuen Namen als String übergebe wie für SetMachineName
. Also bin ich ratlos.
Hier ist der WMI-Code, der die Maschine umbenennt:
/// <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;
}
}
}
Und hier ist der WMI-Code, der es in die Domäne beitritt:
/// <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;
}
}
}
Entschuldigt, wenn dieser Code nervtötend dumm aussieht - ich bin neu für WMI, und das ist weitgehend von Beispielen, die ich auf den Interwebs gefunden habe; Wenn es eine klügere/bessere Möglichkeit gibt, dies zu tun, dann demonstriere es auf jeden Fall. Wenn Sie das Problem zur gleichen Zeit lösen können, Bonuspunkte!
Weitere Informationen: der Aufruf von 'SetMachineName' funktioniert, aber der Name sofort nicht ändert -' ipconfig' noch den alten Namen zeigt, und im Systemeigenschaften Suche zeigt den alten Namen von „gefolgt (wird sich ändern bis XXXXXXX nach dem Neustart) ". Wenn 'SetDomainMembership' einen Verwaltungspfad zu System.Environment.MachineName erhält, ist dies immer noch der alte Name und ist falsch (was zu einem fehlerhaften AD-Eintrag und einem fehlgeschlagenen Join führt). Wenn ich stattdessen den neuen Namen als Parameter übergebe, schlägt der WMI-Aufruf mit der Ausnahme 'Nicht gefunden' fehl, vermutlich, weil noch kein Rechner mit diesem neuen Namen fest eingestellt ist. –