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

C#控制台调用PowerShell脚本返回空字符串,求原因排查

问题:C#调用PowerShell脚本返回空字符串,但直接执行脚本正常

用户提供的C#代码如下:

static void Main(string[] args)
{
   string powershellCommand = @"Get-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object { $_.DisplayName -match 'SOLIDWORKS PDM Client' } | Select-Object DisplayName, DisplayVersion, InstallLocation | ConvertTo-Json";
   ExecuteScript(powershellCommand);
}

public static void ExecuteScript(string powershellCommand)
{
    var processStartInfo = new ProcessStartInfo
        {
            FileName = "powershell.exe",
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true,
            Arguments = $"-ExecutionPolicy Bypass -Command \"{powershellCommand}\""
        };

    using (var process = new Process())
    {
        process.StartInfo = processStartInfo;
        process.Start();

        string output = process.StandardOutput.ReadToEnd();
        string error = process.StandardError.ReadToEnd();

        Console.WriteLine("Output:");
        Console.WriteLine(output);

        if (!string.IsNullOrWhiteSpace(error))
        {
            Console.WriteLine("Error:");
            Console.WriteLine(error);
        }
    }
}

直接在Windows PowerShell中执行该脚本可正常返回结果,但通过上述C#代码调用时始终返回空字符串,求原因及解决办法。


原因分析及解决方案

1. 32位/64位进程注册表重定向问题(最可能原因)

Windows系统中,32位进程访问HKLM:\Software路径时,会被自动重定向到HKLM:\Software\Wow6432Node分支。如果SOLIDWORKS PDM Client是64位程序,其卸载信息会存放在64位的HKLM:\Software路径下,而你的C#控制台程序如果默认以32位模式运行(比如VS中默认Any CPU选项勾选了“首选32位”),就会读不到目标注册表项,导致输出为空。

解决办法:

  • 在Visual Studio中,右键项目 → 属性 → 生成 → 目标平台,选择x64后重新编译运行。
  • 或者强制调用对应位数的PowerShell:
    string powershellPath;
    if (Environment.Is64BitProcess)
    {
        powershellPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), @"System32\WindowsPowerShell\v1.0\powershell.exe");
    }
    else
    {
        // 32位进程调用64位PowerShell需用Sysnative路径绕过重定向
        powershellPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), @"Sysnative\WindowsPowerShell\v1.0\powershell.exe");
    }
    

2. PowerShell命令参数转义问题

原代码用双引号包裹PowerShell命令,当命令包含花括号、管道符等特殊字符时,可能出现转义错误,导致命令未正确执行。

解决办法:
修改Arguments格式,用& { ... }包裹命令,避免引号嵌套问题:

Arguments = $"-ExecutionPolicy Bypass -Command & {{ {powershellCommand} }}"

3. 进程未等待完成导致输出读取不完整

原代码未等待PowerShell进程执行完毕就读取输出,可能导致输出未完全写入就被读取,出现空内容。

解决办法:
在process.Start()后添加进程等待代码:

process.WaitForExit();

修正后的完整代码示例
using System;
using System.Diagnostics;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        string powershellCommand = @"Get-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object { $_.DisplayName -match 'SOLIDWORKS PDM Client' } | Select-Object DisplayName, DisplayVersion, InstallLocation | ConvertTo-Json";
        ExecuteScript(powershellCommand);
    }

    public static void ExecuteScript(string powershellCommand)
    {
        string powershellPath;
        // 根据当前进程位数选择对应PowerShell路径
        if (Environment.Is64BitProcess)
        {
            powershellPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), @"System32\WindowsPowerShell\v1.0\powershell.exe");
        }
        else
        {
            powershellPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), @"Sysnative\WindowsPowerShell\v1.0\powershell.exe");
        }

        var processStartInfo = new ProcessStartInfo
        {
            FileName = powershellPath,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true,
            Arguments = $"-ExecutionPolicy Bypass -Command & {{ {powershellCommand} }}"
        };

        using (var process = new Process())
        {
            process.StartInfo = processStartInfo;
            process.Start();
            // 等待进程执行完毕
            process.WaitForExit();

            string output = process.StandardOutput.ReadToEnd();
            string error = process.StandardError.ReadToEnd();

            Console.WriteLine("Output:");
            Console.WriteLine(output);

            if (!string.IsNullOrWhiteSpace(error))
            {
                Console.WriteLine("Error:");
                Console.WriteLine(error);
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 09:30:36