【问题标题】:Attempting to invoke PowerShell function with parameters尝试使用参数调用 PowerShell 函数
【发布时间】:2018-07-18 02:12:40
【问题描述】:

我正在尝试通过 C# 调用所述脚本来执行 PowerShell 脚本中的函数。该函数有两个参数。但是,我收到一个错误,指出该函数不是可识别的 cmdlet、函数等。根据我的代码,有人可以帮助我解决我做错了什么吗?

string powerShellScript = @"D:\TestTransform\transform.ps1";
IDictionary powerShellParameters = new Dictionary<string, string>();
powerShellParameters.Add("configFile", file);
powerShellParameters.Add("transformFile", transformFile);

Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();

using (PowerShell powerShellInstance = PowerShell.Create())
{
    powerShellInstance.Runspace = runspace;
    powerShellInstance.AddScript(powerShellScript);
    powerShellInstance.Invoke();

    powerShellInstance.AddCommand("XmlDocTransform");
    powerShellInstance.AddParameters(powerShellParameters);

    Collection<PSObject> psOutput = powerShellInstance.Invoke(); //breaks here
}

我的 Powershell 脚本:

function XmlDocTransform($xml, $xdt)
{
    if (!$xml -or !(Test-Path -path $xml -PathType Leaf)) {
        throw "File not found. $xml";
    }
    if (!$xdt -or !(Test-Path -path $xdt -PathType Leaf)) {
        throw "File not found. $xdt";
    }

    $scriptPath = $PSScriptRoot + "\"
    Add-Type -LiteralPath "$scriptPath\Microsoft.Web.XmlTransform.dll"

    $xmldoc = New-Object Microsoft.Web.XmlTransform.XmlTransformableDocument;
    $xmldoc.PreserveWhitespace = $true
    $xmldoc.Load($xml);

    $transf = New-Object Microsoft.Web.XmlTransform.XmlTransformation($xdt);
    if ($transf.Apply($xmldoc) -eq $false)
    {
        throw "Transformation failed."
    }
    $xmldoc.Save($xml);
}

【问题讨论】:

  • .... var process = new Process(); .... process.Start();为什么不使用这种方法?
  • 如何创建运行空间来运行多个命令?
  • 不幸的是,这不起作用。我更新了我的代码并包含了 PowerShell 脚本。
  • 您没有在当前范围内执行D:\TestTransform\transform.ps1,因此脚本完成后XmlDocTransform 将消失。在第一个Invoke 之后,您没有清理命令,因此第二个Invoke 有效地调用. {D:\TestTransform\transform.ps1} | XmlDocTransform …powerShellParameters 中的参数名称与 XmlDocTransform 函数中声明的名称不匹配。

标签: c# powershell


【解决方案1】:

您的职能遵循一些社区最佳实践:

function ConvertTo-XmlDoc {
    [CmdletBinding()]
    [OutputType('System.Void')]
    param(
        [Parameter(Position = 0, Mandatory)]
        [ValidateScript({
            if (-not (Test-Path -Path $PSItem -PathType Leaf)) {
                throw "File not found: $PSItem"
            }
            return $true
        })]
        [string] $Xml,

        [Parameter(Position = 1, Mandatory)]
        [ValidateScript({
            if (-not (Test-Path -Path $PSItem -PathType Leaf)) {
                throw "File not found: $PSItem"
            }
            return $true
        })]
        [string] $Xdt
    )

    Add-Type -LiteralPath "$PSScriptRoot\Microsoft.Web.XmlTransform.dll"

    $xmldoc = [Microsoft.Web.XmlTransform.XmlTransformableDocument]::new()
    $xmldoc.PreserveWhitespace = $true
    $xmldoc.Load($Xml)

    $transform = [Microsoft.Web.XmlTransform.XmlTransformation]::new($Xdt)
    if (-not $transform.Apply($xmldoc)) {
        throw 'Transformation failed.'
    }
    $xmldoc.Save($Xml)
}

后面是应该可以工作的代码:

using (var ps = PowerShell.Create())
{
    ps.AddScript($@". 'D:\TestTransform\transform.ps1'; ConvertTo-XmlDoc -Xml {file} -Xdt {transformFile}");

    ps.Invoke();
}

【讨论】:

  • Create 的无重载接受字符串作为其参数:docs.microsoft.com/en-us/dotnet/api/…
  • @PetSerAl The documentation 有点误导。有多个示例,其中起始 Create 调用是一个命令。我已经按照文档中的文字而不是现在的示例更新了我的答案
  • AddCommand 仅期望命令名称,而不是脚本。您应该只将第一个参数中的文件名和false 传递给第二个参数以在当前范围内调用命令。 params 也是 C# 中的关键字。如果你想用它作为标识符,你应该像@params一样使用它。
  • @PetSerAl 感谢您的反馈。我已经更新了我的答案。
猜你喜欢
  • 2018-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-09
  • 2018-09-09
  • 2020-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多