2010-11-15 13 views
7

पर प्रोग्रामेटिक रूप से विंडोज मशीन में शामिल हों, यह this question का डुप्लिकेट नहीं है, हालांकि, जहां उसने डोमेन पर मैन्युअल रूप से सर्वर में शामिल होने की जानकारी मांगी थी (और सही तरीके से रीडायरेक्ट किया गया था) मैं कुछ के साथ मदद की तलाश में हूं कोड जो प्रोग्रामेटिक रूप से एक डोमेन में मशीन में शामिल हो जाता है।एडी डोमेन

परिदृश्य यह है कि हमारे पास एक लॉन्चर सेवा है जो अमेज़ॅन ईसी 2 सर्वर 2008 आर 1 वीएम को तुरंत चालू करती है, वैकल्पिक रूप से उपयोगकर्ता-डेटा स्ट्रीम के माध्यम से मशीन नाम पास करती है। एक प्रक्रिया को हमारी छवियों में बेक किया जाता है जो बूटअप पर किसी नाम के लिए उपयोगकर्ता-डेटा की जांच करता है - यदि कोई मौजूद नहीं है तो वीएम हमारे क्लाउड डोमेन के बाहर रहता है, लेकिन यदि नाम मौजूद है तो मशीन का नाम बदलकर और स्वतः से जुड़ा हुआ है डोमेन।

यहां समस्या है - अगर मैं इस प्रक्रिया को मैन्युअल रूप से शुरू करने के बाद मैन्युअल रूप से चलाता हूं, तो यह बिल्कुल वर्णन के अनुसार काम करता है; मशीन का नाम बदल दिया गया है, और वीएम डोमेन में शामिल हो गया है (हम इसे करने के लिए पुनरारंभ करने के लिए मजबूर करते हैं)।

हालांकि, जब शेड्यूल्ड टास्क (स्टार्टअप पर ट्रिगर) के रूप में चल रहा है, तो मशीन का नाम अपेक्षित होता है, लेकिन बाद में कॉल JoinDomainOrWorkgroup (नीचे देखें) को ईएम 2 द्वारा वीएम को पुराना यादृच्छिक मशीन नाम चुनता है नया नाम यह अभी सौंपा गया है।

यह की एक WMI वापसी कोड में परिणाम है, हम ई भंडार में डिस्कनेक्ट misnamed प्रविष्टि (कि बेतरतीब नाम की) हो जाते हैं और मशीन डोमेन से जुड़ा हुआ नहीं है। वीएम फिर पुनरारंभ होता है, और स्टार्टअप प्रक्रिया के माध्यम से दूसरा पास होता है (असामान्य रूप से ट्रिगर किया जाता है क्योंकि उपयोगकर्ता-डेटा में सामग्री होती है लेकिन मशीन अभी तक डोमेन में नहीं है) सभी समान चरणों को निष्पादित करती है और सफल होती है।

ऐसा लगता है कि मशीन का नाम पहले पास में सेट है लेकिन 'अंतिमकृत' नहीं है, और JoinDomainOrWorkgroup अभी भी मूल नाम देखता है। दूसरे पास पर, मशीन का नाम पहले ही ठीक से सेट हो चुका है, और इसलिए JoinDomainOrWorkgroup अपेक्षा के अनुसार काम करता है। काफी समय से प्रक्रिया स्टार्टअप के दौरान इस तरह से व्यवहार क्यों करती है, लेकिन पहले से शुरू किए गए वीएम पर मैन्युअल रूप से चलाने पर पूरी तरह से काम करती है, क्या मुझे लगता है कि समस्या का केंद्र है।

मैंने नाम बदलने के बीच देरी डालने का प्रयास किया है और दृश्यों के पीछे नाम बदलने के पहले JoinDomainOrWorkgroup पर कॉल करने के मामले में कदम उठाने की कोशिश की गई है, लेकिन इससे मदद नहीं मिली है - और मुझे वास्तव में इसकी उम्मीद नहीं थी , चूंकि मैन्युअल रूप से चलाए जाने पर पूरी प्रक्रिया पूरी तरह से काम करती है। तो शायद यह बूटअप के दौरान मशीन स्थिति में सूक्ष्म अंतर का संयोजन है और कोड में मूर्खतापूर्ण कुछ है।

विधि में System.Environment.MachineName का उपयोग कर शायद अनावश्यक है? लेकिन अगर मैं SetMachineName के लिए करता हूं तो मैं स्ट्रिंग के रूप में नया नाम पास करता हूं, भले ही यह विफल हो जाता है। तो मैं फंस गया हूँ।

/// <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 कोड है कि यह डोमेन के लिए मिलती है बताया गया है::

यहाँ 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 बेवकूफ लग रहा है - मैं मैं डब्लूएमआई के लिए नया हूं, और यह मुख्य रूप से इंटरवब्स पर मिले उदाहरणों से लिया गया है; यदि ऐसा करने के लिए एक स्मार्ट/साफ तरीका है तो हर तरह से प्रदर्शन करें। यदि आप एक ही समय में समस्या का इलाज कर सकते हैं, बोनस अंक!

+0

अधिक जानकारी: 'को SetMachineName' काम करता है, लेकिन नाम तुरन्त परिवर्तन नहीं करता कॉल -" 'ipconfig' अभी भी पुराने नाम से पता चलता है, और सिस्टम गुण को देख के बाद पुराने नाम से पता चलता (बदल जाएगा पुनरारंभ करने के बाद XXXXXXX पर) "। यदि 'SetDomainMembership' को सिस्टम के लिए प्रबंधन पथ मिलता है। पर्यावरण। माचिननाम, यह अभी भी पुराना नाम है और गलत है (टूटी हुई एडी प्रविष्टि और असफल असफल होने के कारण)। यदि मैं पैरामीटर के रूप में नया नाम पास करता हूं, तो डब्लूएमआई कॉल 'नहीं मिला' अपवाद के साथ विफल रहता है, संभवतः क्योंकि इस नए नाम के साथ मशीन अभी तक सेट नहीं है। –

उत्तर

5

ठीक है, यह है।

सबसे पहले, सिस्टम प्रॉपर्टीज में फ़ील्ड्स का क्रम थोड़ा भ्रामक है - आप मशीन का नाम पहले देखते हैं, और उसके नीचे डोमेन/वर्कग्रुप देखते हैं। इस अवचेतन रूप से मेरी सोच को प्रभावित किया, और इसका मतलब है कि मेरे कोड ने पहले नाम सेट करने की कोशिश करके आदेश दिया है, और फिर डोमेन में मशीन से जुड़ें। हालांकि यह कुछ परिस्थितियों में काम करता है, यह लगातार या भरोसेमंद नहीं है। तो यहां सबसे बड़ा सबक सीखा है ...

पहले डोमेन में शामिल हों - फिर मशीन नाम बदलें।

हाँ, वास्तव में यह सब कुछ है। कई परीक्षण पुनरावृत्तियों के बाद, अंत में यह मेरे सामने आया कि अगर मैं इसे इस तरह से करने की कोशिश करता तो यह बेहतर काम कर सकता है। मैंने अपने पहले पास पर नाम बदलने के लिए ट्रिप-अप किया, लेकिन जल्दी ही एहसास हुआ कि यह अभी भी स्थानीय सिस्टम क्रेडेंशियल्स का उपयोग कर रहा था - लेकिन अब जब मशीन इस बिंदु पर डोमेन में शामिल हो गई थी, तो इसे उसी डोमेन क्रेडेंशियल्स की आवश्यकता थी डोमेन में शामिल होने के लिए। बाद में कोड-ट्वीकिंग का एक तेज़ बिट, और अब हमारे पास लगातार विश्वसनीय विश्वसनीय WMI दिनचर्या है जो डोमेन में शामिल हो जाती है और फिर नाम बदलती है।

यह सबसे अच्छा कार्यान्वयन नहीं हो सकता है (सुधार पर टिप्पणी करने के लिए स्वतंत्र महसूस करें) लेकिन यह काम करता है। का आनंद लें।

/// <summary> 
/// Join domain and set Machine Name 
/// </summary> 
public static bool JoinAndSetName(string newName) 
{ 
    _lh.Log(LogHandler.LogType.Debug, string.Format("Joining domain and changing Machine Name from '{0}' to '{1}'...", Environment.MachineName, newName)); 

    // Get WMI object for this machine 
    using (ManagementObject wmiObject = new ManagementObject(new ManagementPath("Win32_ComputerSystem.Name='" + Environment.MachineName + "'"))) 
    { 
    try 
    { 
     // Obtain in-parameters for the method 
     ManagementBaseObject inParams = wmiObject.GetMethodParameters("JoinDomainOrWorkgroup"); 
     inParams["Name"] = "domain_name"; 
     inParams["Password"] = "domain_account_password"; 
     inParams["UserName"] = "domain_account"; 
     inParams["FJoinOptions"] = 3; // Magic number: 3 = join to domain and create computer account 

     _lh.Log(LogHandler.LogType.Debug, string.Format("Joining machine to domain under name '{0}'...", inParams["Name"])); 

     // Execute the method and obtain the return values. 
     ManagementBaseObject joinParams = wmiObject.InvokeMethod("JoinDomainOrWorkgroup", inParams, null); 

     _lh.Log(LogHandler.LogType.Debug, string.Format("JoinDomainOrWorkgroup return code: '{0}'", joinParams["ReturnValue"])); 

     // Did it work? 
     if ((uint)(joinParams.Properties["ReturnValue"].Value) != 0) 
     { 
     // Join to domain didn't work 
     _lh.Log(LogHandler.LogType.Fatal, string.Format("JoinDomainOrWorkgroup failed with return code: '{0}'", joinParams["ReturnValue"])); 
     return false; 
     } 
    } 
    catch (ManagementException e) 
    { 
     // Join to domain didn't work 
     _lh.Log(LogHandler.LogType.Fatal, string.Format("Unable to join domain '{0}'", _targetDomain), e); 
     return false; 
    } 

    // Join to domain worked - now change name 
    ManagementBaseObject inputArgs = wmiObject.GetMethodParameters("Rename"); 
    inputArgs["Name"] = newName; 
    inputArgs["Password"] = "domain_account_password"; 
    inputArgs["UserName"] = "domain_account"; 

    // Set the name 
    ManagementBaseObject nameParams = wmiObject.InvokeMethod("Rename", inputArgs, null); 
    _lh.Log(LogHandler.LogType.Debug, string.Format("Machine Rename return code: '{0}'", nameParams["ReturnValue"])); 

    if ((uint)(nameParams.Properties["ReturnValue"].Value) != 0) 
    { 
     // Name change didn't work 
     _lh.Log(LogHandler.LogType.Fatal, string.Format("Unable to change Machine Name from '{0}' to '{1}'", Environment.MachineName, newName)); 
     return false; 
    } 

    // All ok 
    return true; 
    } 
} 
संबंधित मुद्दे