目录
介绍
C#允许你从内部执行PowerShell命令。此类命令的结果将传递给此类对象的单个PSObject或集合。反过来,PSObject可以有一个成员集合,每个成员都有一个单独的名称和值。
执行PowerShell命令时,默认情况下,这些结果通常以文本字符串的形式显示在表中。使用fl命令格式化后,我们以name:value的形式获得每对属性的视图。
在本文中,我将介绍如何轻松地将PSObjects转换为具有适当属性的程序员定义的类的对象。
初步假设
每个PSObject表示一个PowerShell命令结果记录,其中包含该命令的特定数量的值以及特定名称。值还具有特定于给定命令的类型。
结果记录类型及其结构的描述当然可以在Microsoft的文档中找到,但是由于PowerShell命令的数量和文档的可用性,这些信息并不容易找到。
但是,我们可以很容易地计算出我们感兴趣的结果记录的结构。
使用PowerShell本身
我们使用fl修饰符执行我们感兴趣的命令。理想情况下,该命令应返回单个记录,而不是集合。
Get-Process lsass |fl
显示的值的集合
Id : 836
Handles: 2078
CPU : 16.625
SI : 0
Name : lsass
通知我们结果记录有5个值,分别按顺序命名Id、句柄、CPU、SI和名称。文本中的当前值显示在每个名称的右侧。
使用C#时
在获得PSObject与PowerShell.Invoke我们有相同的效果使用:
foreach (var member in PSObject.Members)
{
Console.WriteLine (member.Name + ":" + member.Value.ToString ());
}
现在,您必须为Get-Process命令定义一个结果记录类:
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;
}
线索
现在,我们应该为我们的类配备一种方法,该方法将从PSObject成员中提取值并将它们插入到相应的类属性中。
最简单的方法是查看PSObject的成员并将每个成员的名称与类属性的名称进行匹配。当我们为属性找到合适的名称时,我们以文本形式输入值。
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();
但是,这样的枚举不是很漂亮。如果我们有一个具有几十个(或更多)属性的类怎么办?
在C#中的每个类中,您可以通过获取程序员以文本字符串形式为属性指定的名称来浏览其属性。
有一个方法
Class_Name.GetType().GetProperties()
返回属性集合,您可以在其中访问名称和值修改。
从这里开始,我们可以轻松地在PSObject中自动搜索适合于特定属性的值。
foreach (var prop in MyClass.GetType().GetProperties())
{
prop.SetValue(MyClass, pso.Members[prop.Name].Value.AsString());
}
请注意,在我们定义的类中,为了反映PowerShell命令结果记录的属性,我们不必放置所有属性,而只需放置感兴趣的属性。PSObject成员解析方法将只选择我们定义的那些,而不会在其余部分花费任何时间。
代码
下面我介绍一个带有值解析过程的示例结果记录类。该过程稍微复杂一些,以便在结果记录中的某些值为null时不会生成错误。
您可以轻松地将此代码片段更改为项目所需的类。
//The class name may be changed in order to match a PowerShell command.
public class ResultRecordItem
{
//We can add here the next values shown as a result of the PowerShell command and remove unnecessary ones.
//Property types MUST be text or we need to be able to detect the type and use the correct converter in the parsing procedure.
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()));
}
//Here we can add procedures to transform the read values.
//Or creating new text values based on those already obtained.
}
}
https://www.codeproject.com/Tips/5335001/Retrieving-data-from-executed-commands-in-PowerShe