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

.NET Framework Windows服务中PowerShell.Invoke<T>类型参数推断失败问题

.NET Framework Windows服务中调用PowerShell脚本出现类型推断错误

我有一个.NET Framework Windows服务项目,需要在其中运行PowerShell脚本。相同代码在控制台应用中运行正常,但在服务项目中报错:无法从用法中推断方法‘PowerShell.Invoke()’的类型参数,请尝试显式指定类型参数。

代码如下:

private Thread workerThread;
private bool running;
private static readonly ILog log = LogManager.GetLogger(typeof(Service1));

public Service1()
{
    InitializeComponent();
}

protected override void OnStart(string[] args)
{
    running = true;
    workerThread = new Thread(WorkerThreadProc);
    workerThread.Start();
}

protected override void OnStop()
{
    running = false;
    workerThread.Join();
}

private static void WorkerThreadProc()
{
    bool running = true;
    using (var runspace = RunspaceFactory.CreateRunspace())
    {
        runspace.Open();

        while (running)
        {
            try
            {
                string powerShellCommand = "Get-Process";
                string output = RunPowerShellCommand(powerShellCommand);
                string directoryPath = @"C:\HttpConnector\Output";
                string fileName = "PsOutput.txt";
                string filePath = Path.Combine(directoryPath, fileName);

                if (!Directory.Exists(directoryPath))
                {
                    Directory.CreateDirectory(directoryPath);
                }

                WriteToFile(filePath, output);
            }
            catch (Exception ex)
            {
                log.Error("Hata oluştu.", ex);
            }

            TimeSpan interval = TimeSpan.FromMinutes(1);
            Thread.Sleep(interval);
        }

        runspace.Close();
    }
}

private static string RunPowerShellCommand(string command)
{
    using (var runspace = RunspaceFactory.CreateRunspace())
    {
        runspace.Open();

        using (var ps = PowerShell.Create())
        {
            ps.Runspace = runspace;
            ps.AddScript(command);

            try
            {
                var results = ps.Invoke();
                var output = GetObjectInfo(results);
                return output;
            }
            catch (Exception ex)
            {
                log.Error("Hata oluştu: " + ex.ToString());
                return string.Empty;
            }
        }
    }
}

private static string GetObjectInfo(Collection<PSObject> psObjects)
{
    string output = string.Empty;

    foreach (var psObject in psObjects)
    {
        output += $"{psObject.ToString()}{Environment.NewLine}";
    }

    return output;
}

已安装的NuGet包:

  • Microsoft.PowerShell.SDK
  • System.Management.Automation

问题原因与解决方法

原因分析

Windows服务的运行上下文对编译器类型推断的限制比控制台应用更严格,导致无法自动识别PowerShell.Invoke<T>()的泛型参数类型,而控制台应用环境的类型推断规则更宽松,因此未触发该错误。

解决步骤

  1. 显式指定泛型参数:将ps.Invoke()修改为ps.Invoke<PSObject>(),明确告知编译器返回类型为Collection<PSObject>,与后续GetObjectInfo方法的参数类型匹配。
  2. 修复线程循环停止问题:WorkerThreadProc中的局部running变量会导致服务停止时循环无法终止,需改为使用类级别的running字段。

修改后的关键代码

修正后的RunPowerShellCommand方法

private static string RunPowerShellCommand(string command)
{
    using (var runspace = RunspaceFactory.CreateRunspace())
    {
        runspace.Open();

        using (var ps = PowerShell.Create())
        {
            ps.Runspace = runspace;
            ps.AddScript(command);

            try
            {
                // 显式指定泛型参数PSObject
                var results = ps.Invoke<PSObject>();
                var output = GetObjectInfo(results);
                return output;
            }
            catch (Exception ex)
            {
                log.Error("发生错误: " + ex.ToString());
                return string.Empty;
            }
        }
    }
}

修正后的WorkerThreadProc方法

private void WorkerThreadProc()
{
    using (var runspace = RunspaceFactory.CreateRunspace())
    {
        runspace.Open();

        while (running) // 使用类成员变量替代局部变量
        {
            try
            {
                string powerShellCommand = "Get-Process";
                string output = RunPowerShellCommand(powerShellCommand);
                string directoryPath = @"C:\HttpConnector\Output";
                string fileName = "PsOutput.txt";
                string filePath = Path.Combine(directoryPath, fileName);

                if (!Directory.Exists(directoryPath))
                {
                    Directory.CreateDirectory(directoryPath);
                }

                WriteToFile(filePath, output);
            }
            catch (Exception ex)
            {
                log.Error("发生错误.", ex);
            }

            TimeSpan interval = TimeSpan.FromMinutes(1);
            Thread.Sleep(interval);
        }

        runspace.Close();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 03:22:35