如何从C#向PowerShell脚本传递引用参数

3

我似乎无法从C#向PowerShell传递引用参数。我一直收到以下错误:

"System.Management.Automation.ParentContainsErrorRecordException:无法处理参数'Test'的参数转换。在参数中需要引用类型。"

示例:

对于简单的脚本:

Param (
[ref]
$Test
)

$Test.Value = "Hello"
Write-Output $Test

以下是C#代码:

string script = {script code from above};
PowerShell ps = PowerShell.Create();
ps = ps.AddScript($"New-Variable -Name \"Test\" -Value \"Foo\""); // creates variable first
ps = ps.AddScript(script)
        .AddParameter("Test", "([ref]$Test)"); // trying to pass reference variable to script code

ps.Invoke(); // when invoked, generates error "Reference type is expected in argument

我已经尝试过AddParameter和AddArgument。
我成功的方法是首先将脚本创建为脚本块:
ps.AddScript("$sb = { ... script code ...}"); // creates script block in PowerShell
ps.AddScript("& $sb -Test ([ref]$Test)"); // executes script block and passes reference parameter
ps.AddScript("$Test"); // creates output that shows reference variable has been changed

需要帮忙吗?


1
你需要什么帮助?你已经表明了你可以通过脚本块的方法得到结果。为什么要为了不同的东西而感到压力呢?为什么你认为使用脚本块是一件坏事呢? - undefined
1
说得对 - 我应该说我想要了解为什么我的第一种方法不起作用,以便更好地理解C#与PowerShell的接口,因为文档非常有限。 - undefined
1
要注意的是,@mklement0提供的解决方案比我的脚本块方法更好,因为我不需要在PowerShell中显式输出[ref]变量来知道输出变量。相反,我只需检查我传递给AddParameter的C# PSReference对象即可。 - undefined
明白了。因此,请更新您的帖子,以显示您所做的工作,以便其他可能需要相同方法的人能够更清楚地理解。 - undefined
1个回答

3
我无法似乎无法从C#向PowerShell传递引用参数。唯一使您原始方法起作用的方法是在C#中创建您的[ref]实例并将其传递,这意味着创建System.Management.Automation.PSReference实例并将其传递到您的.AddParameter()调用:
// Create a [ref] instance in C# (System.Management.Automation.PSReference)
var psRef = new PSReference(null);

// Add the script and pass the C# variable containing the
// [ref] instance to the script's -Test parameter.
ps.AddScript(script).AddParameter("Test", psRef);

ps.Invoke();

// Verify that the C# [ref] variable was updated.
Console.WriteLine($"Updated psRef: [{psRef.Value}]");

上述代码输出结果为更新后的psRefVar: [Hello]
完整代码:
using System;
using System.Management.Automation;

namespace demo
{
  class Program
  {
    static void Main(string[] args)
    {
      var script = @"
        Param (
        [ref]
        $Test
        )

        $Test.Value = 'Hello'
        Write-Output $Test
        ";

      using (PowerShell ps = PowerShell.Create())
      {
        var psRef = new PSReference(null);
        ps.AddScript(script).AddParameter("Test", psRef);
        ps.Invoke();
        Console.WriteLine($"Updated psRef: [{psRef.Value}]");
      }

    }
  }
}

太棒了 - 谢谢!很有道理。你能解释一下AddParameter和AddArgument之间的真正区别吗?它们只是AddParameter有名称,而AddArgument依赖于PowerShell脚本引用$args[]数组这一点吗?再次感谢。 - undefined
1
很高兴听到对你有帮助,@MikeOliver;一个参数是一个“无名”的值(仅仅是一个值,没有参数名称),通过“位置”传递。为了保证稳健性,你应该使用.AddParameter()。这样解释清楚了吗? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接