You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过PowerShell SDK在C#中访问PowerShell对象的值?

问题:C# Windows服务调用PowerShell仅输出对象类型而非实际值

问题背景

我是C#与.NET编程新手,正在将一段PowerShell脚本转换为功能等效的Windows服务代理。该代理编译、安装正常,可将PowerShell命令输出写入日志文件,但日志仅打印对象类型而非实际值,需要解决如何正确访问PowerShell对象中的值的问题。

相关代码示例(错误写法)

using System.Management.Automation;
using System.IO;
using System;

// Windows服务中调用PowerShell的核心代码
public void ExecutePowerShellCommand()
{
    using (var ps = PowerShell.Create())
    {
        ps.AddCommand("Get-Service")
          .AddParameter("Name", "WinRM");
        
        var results = ps.Invoke();

        // 错误:直接ToString()仅输出对象类型
        foreach (var result in results)
        {
            File.AppendAllText(@"C:\service.log", result.ToString() + Environment.NewLine);
        }
    }
}

日志输出示例

System.Management.Automation.PSCustomObject

原PowerShell脚本

# 原脚本:获取指定服务的名称与状态
Get-Service -Name WinRM | Select-Object Name, Status, StartType

解决方案

1. 直接访问对象属性(推荐)

PowerShell返回的是PSCustomObject实例,可通过Properties集合或dynamic类型直接读取属性值:

方式1:使用Properties集合(类型安全)

foreach (var result in results)
{
    // 读取属性值,需先检查属性是否存在
    var serviceName = result.Properties.ContainsKey("Name") ? result.Properties["Name"].Value : "N/A";
    var serviceStatus = result.Properties.ContainsKey("Status") ? result.Properties["Status"].Value : "N/A";
    var startType = result.Properties.ContainsKey("StartType") ? result.Properties["StartType"].Value : "N/A";

    File.AppendAllText(@"C:\service.log", 
        $"服务名称: {serviceName}, 状态: {serviceStatus}, 启动类型: {startType}{Environment.NewLine}");
}

方式2:使用dynamic类型(简化代码)

foreach (dynamic result in results)
{
    // 直接通过属性名访问,需确保属性存在
    string serviceName = result.Name;
    string serviceStatus = result.Status.ToString();
    string startType = result.StartType.ToString();

    File.AppendAllText(@"C:\service.log", 
        $"服务名称: {serviceName}, 状态: {serviceStatus}, 启动类型: {startType}{Environment.NewLine}");
}

2. 获取PowerShell格式化输出(与控制台一致)

如果需要和PowerShell控制台输出完全相同的文本格式,可在脚本中添加Out-String命令:

using (var ps = PowerShell.Create())
{
    // 原脚本末尾添加Out-String,将对象转换为格式化文本
    ps.AddScript(@"Get-Service -Name WinRM | Select-Object Name, Status, StartType | Out-String");
    var results = ps.Invoke();

    foreach (var result in results)
    {
        File.AppendAllText(@"C:\service.log", result.ToString() + Environment.NewLine);
    }
}

3. 处理空值与错误

调用PowerShell时需处理可能的空结果或错误,避免空引用异常:

using (var ps = PowerShell.Create())
{
    ps.AddCommand("Get-Service")
      .AddParameter("Name", "WinRM");
    
    var results = ps.Invoke();

    // 处理错误流
    if (ps.Streams.Error.Count > 0)
    {
        foreach (var error in ps.Streams.Error)
        {
            File.AppendAllText(@"C:\service.log", $"错误: {error.Message}{Environment.NewLine}");
        }
    }

    // 处理空结果
    if (results.Count == 0)
    {
        File.AppendAllText(@"C:\service.log", "未找到指定服务" + Environment.NewLine);
        return;
    }

    // 读取属性值
    foreach (var result in results)
    {
        var serviceName = result.Properties["Name"]?.Value ?? "N/A";
        File.AppendAllText(@"C:\service.log", $"服务名称: {serviceName}{Environment.NewLine}");
    }
}

原因说明

PowerShell命令返回的是.NET对象(如PSCustomObject),直接调用ToString()方法默认返回对象的类型名称,而非对象的属性内容。必须显式访问对象的属性,或通过Out-String将对象转换为格式化文本,才能获取实际业务值。

内容的提问来源于stack exchange,提问作者Patrick Carra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 18:13:09