2010-11-15 20 views
7

Điều này tương tự, nhưng không phải là sự lừa đảo, this question - tuy nhiên, nơi nó tìm kiếm thông tin về cách tham gia máy chủ theo cách thủ công vào miền (và đã được chuyển hướng đúng) Tôi đang tìm trợ giúp với một số mã lập trình tham gia một máy vào miền.Lập trình tham gia máy Windows vào miền AD

Kịch bản là chúng tôi có dịch vụ trình khởi chạy instantiates máy chủ Amazon EC2 Server2008R1, tùy chọn chuyển Tên Máy qua luồng Người dùng-Dữ liệu. Một quá trình được đưa vào ảnh của chúng ta để kiểm tra User-Data cho một tên khi khởi động - Nếu không có thì VM vẫn ở bên ngoài miền Cloud của chúng ta, nhưng nếu tên đó có mặt thì máy sẽ được đổi tên như được chỉ định và tự động kết nối lĩnh vực.

Đây là vấn đề - nếu tôi chạy quy trình này theo cách thủ công bất kỳ lúc nào sau khi bắt đầu bắt đầu, nó hoạt động chính xác như mô tả; tên máy được thay đổi và máy ảo được nối với miền (chúng tôi buộc khởi động lại để thực hiện điều này).

Tuy nhiên, khi chạy dưới dạng tác vụ theo lịch biểu (được kích hoạt khi khởi động), quá trình đổi tên máy sẽ diễn ra như mong đợi, nhưng cuộc gọi tiếp theo là JoinDomainOrWorkgroup (xem bên dưới) chọn tên máy ngẫu nhiên cũ cho máy ảo bằng EC2 thay vì tên mới nó vừa được gán.

Điều này dẫn đến mã trả về WMI là , chúng tôi nhận được mục nhập sai tên trong kho lưu trữ AD (tên ngẫu nhiên) và máy không được nối với miền. VM sau đó khởi động lại, và bước thứ hai thông qua quá trình khởi động (được kích hoạt bất thường vì có nội dung trong User-Data nhưng máy chưa nằm trong miền) thực hiện tất cả các bước tương tự và thành công.

Có vẻ như tên máy được đặt trong dấu đầu tiên nhưng không được 'hoàn thành' và JoinDomainOrWorkgroup vẫn thấy tên gốc. Trên đèo thứ hai, tên máy đã được đặt đúng cách và do đó, JoinDomainOrWorkgroup hoạt động như mong đợi. Khá lý do tại sao quá trình này hoạt động theo cách này trong khi khởi động, nhưng hoạt động hoàn hảo khi chạy thủ công trên một máy ảo đã bắt đầu, là tôi nghĩ rằng vấn đề của vấn đề.

Tôi đã thử chèn thời gian trễ giữa đổi tên và tham gia các bước trong trường hợp cuộc gọi đến JoinDomainOrWorkgroup xảy ra trước khi đổi tên được hoàn thành sau hậu trường, nhưng điều này đã không giúp - và tôi thực sự không mong đợi , vì toàn bộ quá trình hoạt động hoàn hảo khi chạy thủ công. Vì vậy, nó có thể là một sự kết hợp của một sự khác biệt tinh tế trong trạng thái máy trong quá trình khởi động và một cái gì đó ngớ ngẩn trong mã.

Có thể sử dụng System.Environment.MachineName trong phương pháp SetDomainMembership là không thể lưu ý? Nhưng nó stil thất bại ngay cả khi tôi vượt qua tên mới trong như một chuỗi như tôi làm cho SetMachineName. Vì vậy, tôi stumped.

Dưới đây là mã WMI rằng đổi tên máy:

/// <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; 
    } 
    } 
} 

Và đây là mã WMI rằng gia nhập nó vào miền:

/// <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; 
    } 
    } 
} 

Xin lỗi nếu mã này có vẻ tâm-numbingly ngu ngốc - Tôi là mới đối với WMI, và điều này phần lớn được cribbed từ các ví dụ tôi đã tìm thấy trên interwebs; nếu có một cách thông minh hơn/neater để làm điều này thì bằng mọi cách chứng minh. Nếu bạn có thể chữa trị vấn đề cùng một lúc, điểm thưởng!

+0

Thông tin khác: lệnh gọi 'SetMachineName' hoạt động, nhưng tên không thay đổi ngay lập tức -' ipconfig' vẫn hiển thị tên cũ và xem Thuộc tính hệ thống hiển thị tên cũ theo sau "(sẽ thay đổi tới XXXXXXX sau khi khởi động lại) ". Nếu 'SetDomainMembership' có một đường dẫn quản lý đến System.Environment.MachineName, thì đây vẫn là tên cũ và không chính xác (dẫn đến một mục AD bị hỏng và một tham gia không thành công). Thay vào đó, nếu tôi chuyển tên mới dưới dạng tham số, cuộc gọi WMI sẽ không thành công với ngoại lệ 'Không tìm thấy', có lẽ do chưa có một máy có tên mới được đặt chắc chắn. –

Trả lời

5

OK, đây rồi.

Thứ nhất, thứ tự của các trường trong Thuộc tính hệ thống hơi gây hiểu nhầm - bạn thấy Tên máy đầu tiên và Miền/Nhóm làm việc bên dưới. Điều này ảnh hưởng tiềm thức đến suy nghĩ của tôi, và có nghĩa là mã của tôi đã sao chép thứ tự đó bằng cách cố gắng đặt tên trước, và sau đó kết nối máy với miền. Trong khi điều này làm việc trong một số trường hợp, nó không phù hợp hoặc đáng tin cậy. Vì vậy, bài học lớn nhất được học ở đây là ...

Tham gia miền trước - sau đó thay đổi tên máy.

Đúng, đó thực sự là tất cả. Sau nhiều lần kiểm tra lặp lại, cuối cùng tôi đã nhận ra rằng nó có thể hoạt động tốt hơn nếu tôi thử nó theo cách này. Tôi đã vấp phải sự thay đổi tên trên pass đầu tiên, nhưng nhanh chóng nhận ra rằng nó vẫn đang sử dụng các thông tin hệ thống cục bộ - nhưng bây giờ máy đã được join vào miền tại thời điểm này, nó cần các thông tin đăng nhập miền giống như đã được sử dụng để tự tham gia miền. Một chút chỉnh sửa mã sau này, và bây giờ chúng tôi có một thường lệ WMI đáng tin cậy tham gia vào miền và sau đó thay đổi tên.

Nó có thể không được thực hiện gọn gàng nhất (cảm thấy tự do để bình luận về cải tiến) nhưng nó hoạt động. Thưởng thức.

/// <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; 
    } 
} 
Các vấn đề liên quan