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

在WinForm C#中用PowerShell RunSpace执行两脚本结果一致问题求助

问题与解决方案

问题描述

使用Visual Studio 2017开发WinForm C#程序时,通过PowerShell RunSpace执行以下两个PowerShell脚本后,生成的InstalledSoftwareList1.txt和InstalledSoftwareList2.txt内容完全相同:

# 脚本1
Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName | Format-Table –AutoSize > C:\Temp\InstalledSoftwareList1.txt

# 脚本2
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |  Select-Object DisplayName | Format-Table –AutoSize > C:\Temp\InstalledSoftwareList2.txt

但在PowerShell ISE中执行相同脚本,能得到预期的两个不同结果。当前WinForm中执行PowerShell的代码如下:

private string RunScript(string script)
{
    Runspace runspace = RunspaceFactory.CreateRunspace();
    runspace.Open();
    Pipeline pipeline = runspace.CreatePipeline();
    pipeline.Commands.AddScript(script);
    pipeline.Commands.Add("Out-String");
    Collection<PSObject> results = pipeline.Invoke();
    runspace.Close();
    StringBuilder stringBuilder = new StringBuilder();
    foreach (PSObject pSObject in results)
        stringBuilder.AppendLine(pSObject.ToString());
    return stringBuilder.ToString();
}

调用方式:

RunScript(@"Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName | Format-Table –AutoSize > C:\Temp\InstalledSoftwareList1.txt");

RunScript(@"Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |  Select-Object DisplayName | Format-Table –AutoSize > C:\Temp\InstalledSoftwareList2.txt");

原因分析

核心问题是注册表重定向机制:

  • 32位进程访问HKLM:\Software路径时,Windows会自动将请求重定向到HKLM:\Software\Wow6432Node。
  • Visual Studio默认编译WinForm项目时,AnyCPU配置下会勾选“首选32位”选项,导致程序以32位模式运行。此时不管脚本中指定的是HKLM:\Software还是HKLM:\Software\Wow6432Node,实际访问的都是同一个注册表路径,所以生成的文件内容完全一致。
  • 而PowerShell ISE默认以64位模式运行(在64位系统上),能正确区分两个不同的注册表路径,因此得到不同结果。

解决方案

方案1:修改项目编译配置

  1. 在Visual Studio中右键项目 → 选择“属性”。
  2. 切换到“生成”选项卡。
  3. 取消勾选“首选32位”(仅适用于AnyCPU平台),或者直接将目标平台改为x64。
  4. 重新编译运行程序,此时程序以64位模式运行,不会触发注册表重定向,两个脚本将访问不同的注册表路径,生成预期的不同结果。

方案2:在RunSpace中指定64位PowerShell

如果需要保持程序为32位,但要访问64位注册表,可以创建64位的RunSpace:

private string RunScript(string script)
{
    var runspaceConfig = RunspaceConfiguration.Create();
    var runspace = RunspaceFactory.CreateRunspace(runspaceConfig);
    // 强制启用64位模式(仅当程序以32位运行时生效)
    runspace.Open(new RunspaceConnectionInfo { ProcessArchitecture = Architecture.X64 });
    
    Pipeline pipeline = runspace.CreatePipeline();
    pipeline.Commands.AddScript(script);
    pipeline.Commands.Add("Out-String");
    Collection<PSObject> results = pipeline.Invoke();
    runspace.Close();
    
    StringBuilder stringBuilder = new StringBuilder();
    foreach (PSObject pSObject in results)
        stringBuilder.AppendLine(pSObject.ToString());
    return stringBuilder.ToString();
}

方案3:禁用注册表重定向(仅适用于32位进程)

在访问注册表前禁用重定向,访问后恢复:

// 导入Windows API函数
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);

// 修改RunScript方法,添加禁用重定向逻辑
private string RunScript(string script)
{
    IntPtr ptr = IntPtr.Zero;
    bool disableSuccess = Wow64DisableWow64FsRedirection(ref ptr);
    
    Runspace runspace = RunspaceFactory.CreateRunspace();
    runspace.Open();
    Pipeline pipeline = runspace.CreatePipeline();
    pipeline.Commands.AddScript(script);
    pipeline.Commands.Add("Out-String");
    Collection<PSObject> results = pipeline.Invoke();
    runspace.Close();
    
    // 恢复重定向
    if (disableSuccess)
        Wow64RevertWow64FsRedirection(ptr);
    
    StringBuilder stringBuilder = new StringBuilder();
    foreach (PSObject pSObject in results)
        stringBuilder.AppendLine(pSObject.ToString());
    return stringBuilder.ToString();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:25:25