Programmatisch beitreten Windows-Rechner zu AD-Domäne
Dies ist ähnlich, aber kein dupe, diese Frage - jedoch, wo es versucht, Informationen auf manuell Beitritt eines Servers zu einer Domäne (und wurde zu Recht Weiterleitung) ich bin auf der Suche nach Hilfe mit irgendeinem code, der programmatisch reiht sich in eine Maschine zu einer Domäne.
Szenario ist, dass wir ein launcher-Dienst instanziiert Amazon EC2 Server2008R1 VMs, Optional ist übergabe einer Maschine Namens durch den Nutzer-Datenstrom. Ein Prozess ist eingebettet in unsere Bilder, die Kontrollen der User-Daten für einen Namen auf Booten - Falls keiner vorhanden ist, dann der VM bleibt außerhalb unserer Cloud domain, aber wenn der name vorhanden ist, dann ist die Maschine umbenannt wie angegeben und automatisch mit der Domäne verknüpft.
Hier ist das problem - wenn ich diesen Prozess manuell jederzeit nach Instanz zu starten, es funktioniert genau wie beschrieben; der Computername geändert wird, und die VM der Domäne beigetreten ist (wir haben einen Neustart zu erzwingen, damit dies geschieht).
Aber bei der Ausführung als Geplanter Task (ausgelöst beim Start) der Maschine umbenennen passiert, wie erwartet, aber der nachfolgende Aufruf JoinDomainOrWorkgroup
(siehe unten) nimmt die alte randomisierten Maschine name der VM von EC2-statt mit dem neuen Namen hat es gerade zugewiesen wurde.
Diese Ergebnisse in WMI-return-code von 8525, wir bekommen ein getrenntes irreführend Eintrag in der AD-repository (der, die randomisierte name) und die Maschine ist nicht mit der Domäne verbunden. Die VM startet dann neu, und einen zweiten Durchgang durch die startup-Prozess (ungewöhnlich ausgelöst, da gibt es Inhalte, die im User-Daten, aber die Maschine ist noch nicht in der Domäne) führt alle die gleichen Schritte und gelingt.
Wie es aussieht ist die Maschine name wird im ersten Durchgang aber nicht 'abgeschlossen', und JoinDomainOrWorkgroup
sieht noch den ursprünglichen Namen. Auf dem zweiten pass, der Rechnername ist schon richtig eingestellt, und so JoinDomainOrWorkgroup
funktioniert wie erwartet. Ganz, weshalb das Verfahren auf diese Weise verhält, während des Startvorgangs, aber funktioniert perfekt, wenn manuell ausgeführt auf eine bereits gestartete VM, ist denke ich der Kern des Problems.
Habe ich versucht, das einfügen einer Verzögerung zwischen dem umbenennen und join Schritte im Falle der Aufruf JoinDomainOrWorkgroup
geschah vor dem umbenennen ging hinter die kulissen, aber das hat nicht geholfen - und ich habe nicht wirklich erwarten, dass es, da der gesamte Prozess funktioniert perfekt, wenn manuell ausgeführt. Es ist also wahrscheinlich eine Kombination aus feiner Unterschied in der Zustandsmaschine während dem Booten und etwas dummes in den code.
Vielleicht mit System.Environment.MachineName
im SetDomainMembership
Methode nicht empfehlenswert ist? Aber es stil schlägt fehl, selbst wenn ich den pass der neue name als string, wie ich für SetMachineName
. So bin ich überfragt.
Hier ist der WMI code, benennt der Maschine:
///<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, verbindet es die domain:
///<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 sieht Geist-betäubend dumm - ich bin neu auf WMI, und dies ist im wesentlichen abgekupfert von Beispielen, die ich gefunden habe, auf der interwebs; wenn es ein schlauer/eleganter Weg, dies zu tun, dann mit allen Mitteln zeigen. Wenn Sie heilen kann, das problem in der gleichen Zeit, bonus-Punkte!
- Weitere Informationen: der Aufruf
SetMachineName
funktioniert, aber der name ändert sich nicht, sofort -ipconfig
zeigt immer noch den alten Namen, und suchen auf System-Eigenschaften zeigt die alten Namen gefolgt von "(wird sich ändern, um XXXXXXX nach Neustart)". WennSetDomainMembership
bekommt eine management-Pfad zu System.Umwelt.MachineName, ist dies immer noch die alten Namen und ist falsch (führt zu einem gebrochenen AD-Eintrag und einer gescheiterten join). Wenn ich stattdessen den pass der neue name als parameter, die WMI-Aufruf schlägt fehl mit einem "Nicht Gefunden" - exception, vermutlich, weil es nicht noch eine Maschine mit diesem neuen Namen fest.
Du musst angemeldet sein, um einen Kommentar abzugeben.
OK, hier ist es.
Erstens, die Reihenfolge der Felder in den Systemeigenschaften ist ein wenig irreführend - Sie sehen Machine Name zuerst, und Domäne/Arbeitsgruppe unten. Dies unterbewusst beeinflusst mein denken, und gemeint, mein code kopiert, die Bestellung, indem Sie versuchen, um den Namen zuerst, und dann fügen Sie die Maschine an die Domäne. Während dies funktioniert unter Umständen nicht konsistent oder zuverlässig. Also die größte Lektion, die hier gelernt wird...
Yep, das ist wirklich alles dort ist zu ihm. Nach zahlreichen test-Iterationen, ist es schließlich dämmerte mir, dass es besser laufen könnte, wenn ich versuchte es auf diese Weise um. Stolperte ich-bis auf die änderung der Namen auf meiner ersten pass, aber schnell realisierte, dass es immer noch mit der lokalen Systemanmeldeinformationen - aber jetzt, dass die Maschine an der Domäne an dieser Stelle, es Bedarf der gleichen Domäne-Anmeldeinformationen verwendet wurden, um sich die domain selbst. Eine schnelle bit-code-Optimierungen später, und jetzt haben wir einen konsequent-zuverlässig-WMI-routine, die Mitglied der Domäne, und dann ändert den Namen.
Ist es vielleicht nicht die sauberste Umsetzung (fühlen Sie sich frei zu kommentieren, Verbesserungen), aber es funktioniert. Genießen.