How to quickly create a record class in C # containing the output values of a PowerShell command
Introduction
C # allows you to execute PowerShell commands from within. The results of such a command are passed to a single PSObject
or a collection of such objects. In turn, PSObject
may have a collection of members, each of which has an individual name and value.
When executing a PowerShell command, these results are typically presented in a table as text strings by default. After formatting with the fl command, we get a view of each pair of properties in the form of name: value as text.
In this article, I present how easy translate PSObjects to object of a class defined by a programmer with the appropriate properties.
Preliminary assumptions
Each PSObject
represents a PowerShell command result record containing a specific number of values for that command and also with specific names. Values have types specific to a given command as well.
Result record types and descriptions of their structures are of course available in Microsoft's documentation, but this information is not easy to find due to the number of PowerShell commands and the mere availability of documentation.
However, we can easily work out the structure of the result records that interest us.
Using PowerShell itself:
We execute the command we are interested in with the fl modifier. Ideally, the command should return a single record, not a collection.
Get-Process lsass | fl
Collection of values displayed
Id : 836
Handles: 2078
CPU : 16.625
SI : 0
Name : lsass
informs us that the result record has 5 values named sequentially Id, Handles, CPU, SI and Name. The current values in text are displayed on the right side of each name.
When using C#
after getting PSObject
with PowerShell.Invoke
we have the same effect using:
foreach (var member in PSObject.Members)
{
Console.WriteLine (member.Name + ":" + member.Value.ToString ());
}
Now you would have to define a result record class for the Get-Process command:
public class ProcessItem
{
public string Id {get; set;} = string.Empty;
public string Handles {get; set;} = string.Empty;
public string CPU {get; set;} = string.Empty;
public string SI {get; set;} = string.Empty;
public string Name {get; set;} = string.Empty;
}
Clue
Now we should equip our class with a method that would extract values from PSObject members and insert them into the appropriate class properties.
The easiest way would be to look at the members of PSObject
and match the name of each to the name of the class property. When we find a suitable name for the property, we enter the value in text form.
Id = member["Id"].Value.ToString();
Handles = member["Handles"].Value.ToString();
CPU = member["CPU"].Value.ToString();
SI = member["SI"].Value.ToString();
Name = member["Name"].Value.ToString();
However, such an enumeration is not very pretty. What if we have a class with several dozen (or more) properties?
At each class in C #, you can browse its properties by getting the name given to the property by the programmer in the form of a text string.
There is a method
Class_Name.GetType().GetProperties()
returning a collection of properties where you can access both the name and the value modification.
From here, we can easily automate the search in PSObject
of values appropriate for a specific property.
foreach (var prop in MyClass.GetType().GetProperties())
{
prop.SetValue(MyClass, pso.Members[prop.Name].Value.AsString());
}
Please note that in our defined class, which is to reflect the properties of the PowerShell command result record, we do not have to put all the properties, only those of interest. The PSObject
member parsing method will pick only those we've defined without spending any time on the rest.
Code
Below I present an example result record class with a value parsing procedure. the procedure is a bit more elaborate so as not to generate an error if some values are null in the result record.
You can easily change this code snippet to the class required for your project.
public class ResultRecordItem
{
public string Name {get; set;} = string.Empty;
public string Status {get; set;} = string.Empty;
public string GUID {get; set;} = string.Empty;
public ResultRecordItem() {}
public ResultRecordItem(PSObject pso)
{
foreach (var prop in this.GetType().GetProperties())
{
prop.SetValue(this, (pso.Members[prop.Name].IsNull() ? "" : pso.Members[prop.Name].Value.AsString()));
}
}
}
History
Version 1, written on June 15, 2022.