Skip to content
This repository was archived by the owner on Apr 18, 2020. It is now read-only.

Script Executing Extension Method

Jaime Still edited this page Sep 9, 2016 · 7 revisions

For detailed information on using the System.Management.Automation library, see Writing a Windows PowerShell Host Application.

The Extension Method will be executable on an instance of QueryWmiModel and return an IEnumerable<ResultModel>.

public static async Task<IEnumerable<ResultModel>> QueryWmi(this QueryWmiModel model)

An InitialSessionState is created with the default available cmdlets, and the ExecutionPolicy is set to Unrestricted.

List<ResultModel> results = new List<ResultModel>();
InitialSessionState iss = InitialSessionState.CreateDefault();
iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;

A Runspace context is created, the InitialSessionState is passed into the constructor of the Runspace object, and the runspace is opened.

using (Runspace rs = RunspaceFactory.CreateRunspace(iss))
{
    rs.Open();
    ...
}

The script for the class is retrieved using the GetTextFromEmbeddedResource() extension method, then passed into a new instance of the Command class (true is specified as the second argument to indicate that the command is a script). All of the parameters from the model are added to Command's Parameters collection. Notice that, although the parameters are defined in the script with a $ prefix, they are referenced without.

var script = string.Empty;
script = await ("PowerShellAPIFramework.Core.Scripts.query-wmi.ps1").GetTextFromEmbeddedResource();

Command queryWmi = new Command(script, true);
queryWmi.Parameters.Add("query", model.query);
queryWmi.Parameters.Add("properties", model.properties);
queryWmi.Parameters.Add("computername", model.computername);
queryWmi.Parameters.Add("wmiNamespace", model.wmiNamespace);
queryWmi.Parameters.Add("credential", new PSCredential(model.username, model.securePassword));

A PowerShell context is created, the runspace is assigned, the command is added to the pipeline, and the results are retrieved by invoking the pipeline.

using (PowerShell ps = PowerShell.Create())
{
    ps.Runspace = rs;
    ps.Commands.AddCommand(queryWmi);
    var psResults = ps.Invoke();
}

If the pipeline had errors and the number of error objects in the stream is greater than zero, the exception messages are aggregated using the GetExceptionMessageChain() extensions method and re-thrown.

if (ps.HadErrors)
{
    if (ps.Streams.Errors.Count > 0)
    {
        var exceptions = new StringBuilder();

        foreach (var error in ps.Streams.Error)
        {
            exceptions.AppendLine(error.Exception.GetExceptionMessageChain());
        }

        throw new Exception(excpetions.ToString());
    }
}

Otherwise, the Collection<PSObject> is enumerated, the Properties collection is cast to an IEnumerable<PropertyValueModel>, and assigned to a ResultModel object. After the enumeration completes, the results are returned.

foreach (var result in psResults)
{
    var resultModel = new ResultModel
    {
        propertyValues = result.Properties.Select(x => new PropertyValueModel
        {
            property = x.Name,
            value = x.Value
        }).AsEnumerable()
    };

    results.Add(resultModel);
}
...
return results.AsEnumerable();

If, at any time an exception is caught, the messages are aggregated and re-thrown.

catch (Exception ex)
{
    throw new Exception(ex.GetExceptionMessageChain());
}
Clone this wiki locally