Wednesday, 20 November 2013

Getting server roles and features using WMI on Windows Server 2012 and 2012R2 using the MSFT_ServerManagerDeploymentTasks method GetServerComponentsAsync

I've recently been trying to understand what's happened to the Win32_ServerFeature which Microsoft appear to have ditched in Windows Server 2012.
 
What's happened seems indicative of Microsoft's current attitude towards half finished products and documentation so I'm going to try and help clarify what has happened.
 
Win32_ServerFeature is still available on Windows Server 2012 and R2 however new server features that have been added to the operating system will not appear in the results.
 
The replacement is the GetServerComponentsAsync() method of the MSFT_ServerManagerDeploymentTasks class
 
Unfortunately Microsoft haven't actually bothered to document any of these methods. More scarily they seem to have written incorrect documentation stating that parameters are Strings for example, when they clearly aren't.
 
I've put together a quick WMI call to get the Windows server roles and features using WMI on Windows Server 2012 and above.
 
A few caveats
 
1. This is quick coding... I will finalise this at some point.
 
2. The method is called async but I'm calling it synchronously. I'm not sure why you need to be forced to call the method async, it's not like it's going to be returning terrabytes of data. Also calling it async seems to product AccessDenied errors.
 
Please let me know if this helps. If you're looking at documenting your servers please take a look at XIA Configuration Server our Network Documentation Tool
 
 
 
/// <summary>
/// Represents the state of a request to the Server Manager.
/// </summary>
enum ServerManagerRequestState : byte
{
    /// <summary>
    /// The request is in progress.
    /// </summary>
    InProgress = 0,
 
    /// <summary>
    /// The request has completed.
    /// </summary>
    Completed = 1,
 
    /// <summary>
    /// The request has failed.
    /// </summary>
    Failed = 2,
 
}
 
 
/// <summary>
/// Represents the installation state of a component (server role or feature).
/// </summary>
enum ServerManagerInstalledState : byte
{
    /// <summary>
    /// The component is not installed.
    /// </summary>
    NotInstalled = 0,
 
    /// <summary>
    /// The component is installed.
    /// </summary>
    Installed = 1,
 
    /// <summary>
    /// The component has been installed but requires a reboot to complete.
    /// </summary>
    RebootRequired = 3,
 
}
 
 
/// <summary>
/// Queries the state of the Windows server components.
/// </summary>
public void Query()
{
    Query(Environment.MachineName);
}
 
 
/// <summary>
/// Queries the state of the Windows server components.
/// </summary>
/// <param name="Machinename">The name of the machine to query.</param>
public void Query(String Machinename)
{
    ConnectionOptions Options = new ConnectionOptions();
    ManagementScope Scope = new ManagementScope(String.Format(@"\\{0}\root\Microsoft\Windows\ServerManager", Machinename), Options);
    ManagementClass Tasks = new ManagementClass(Scope, new ManagementPath(@"MSFT_ServerManagerDeploymentTasks"), null);
    ManagementClass RequestGuid = new ManagementClass(Scope, new ManagementPath(@"MSFT_ServerManagerRequestGuid"), null);
    RequestGuid.Properties["HighHalf"].Value = 0;
    RequestGuid.Properties["LowHalf"].Value = 0;
    ManagementBaseObject Parameters = Tasks.GetMethodParameters("GetServerComponentsAsync");
    Parameters["RequestGuid"] = RequestGuid;
    ManagementBaseObject Results = Tasks.InvokeMethod("GetServerComponentsAsync", Parameters, null);
    ManagementBaseObject EnumerationState = (ManagementBaseObject)Results.Properties["EnumerationState"].Value;
    ServerManagerRequestState RequestState = (ServerManagerRequestState)EnumerationState.Properties["RequestState"].Value;
    if (RequestState != ServerManagerRequestState.Completed) { throw new InvalidOperationException(String.Format("Could not determine the installed server components - state {0}.", RequestState)); }
    ManagementBaseObject[] ServerComponents = (ManagementBaseObject[])Results.Properties["ServerComponents"].Value;
    Log(ServerComponents.Length.ToString());
    foreach (ManagementBaseObject ServerComponent in ServerComponents)
    {
        String DisplayName = (String)ServerComponent.Properties["Displayname"].Value;
        ServerManagerInstalledState Installed = (ServerManagerInstalledState)ServerComponent.Properties["Installed"].Value;
        Log(DisplayName + " " + Installed.ToString());
    }
}
 
 
/// <summary>
/// Writes the specified message.
/// </summary>
/// <param name="Message">The message to log.</param>
private void Log(String Message)
{
    textBox1.AppendText(Message + Environment.NewLine);
}
 

No comments:

Post a Comment