尝试从.NET安装程序的自定义操作执行PowerShell 2.0脚本

时间:2010-11-03 17:06:27

标签: c# .net powershell

我已经在这个问题上工作了几天,并在这里阅读了几篇文章,但我无法让我的实现工作。我在Commit自定义操作期间调用powershell脚本。当我到达pipeline.Invoke()方法时,我得到一个异常,说明整个脚本“不被识别为cmdlet,函数,脚本文件或可操作程序的名称。检查名称的拼写,或者是否包含路径,验证路径是否正确,然后重试。“

这是我的剧本:

Param(
    [parameter(Mandatory=$true,ValueFromPipeline=$true)]
    [string]$installPath
    );

schtasks /create /TN MyTask /RU domain\account /RP password /xml $installPath\MyTaskSchedule.xml;

我已经尝试过,有或没有尾随的分号,有和没有包装功能。我已经验证了C#代码正在传递正确的安装路径,并且在执行此步骤之前,xml文件存在于目录中。我可以从PowerShell本身运行它,它可以正常工作。

这是我的代码:

public override void Commit( System.Collections.IDictionary savedState )
{
    base.Commit( savedState );

    String targetDirectory = this.Context.Parameters["TDir"].ToString();
    String script = System.IO.File.ReadAllText( targetDirectory + "TaskScheduler.ps1" );

    RunspaceConfiguration c = RunspaceConfiguration.Create();

    using ( Runspace runspace = RunspaceFactory.CreateRunspace() )
    {
        runspace.Open();
        using ( Pipeline pipeline = runspace.CreatePipeline() )
        {
            Command myCommand = new Command( script );
            CommandParameter param = new CommandParameter( "installPath", targetDirectory.Replace("\\\\", "\\") );

            myCommand.Parameters.Add( param );
            pipeline.Commands.Add( myCommand );

            try
            {
                 pipeline.Invoke();
            }
            catch ( Exception e )
            {
                 MessageBox.Show( e.Message );
            }
        }
    }
}

当在pipeline.Invoke捕获异常时,在上面详述的错误消息之前,将显示整个脚本(使用$ installPath而不是实际路径)作为字符串。我已经在脚本本身内尝试了几次检查,但无论如何都得到相同的结果,这告诉我,runpace只是不喜欢脚本本身。

1 个答案:

答案 0 :(得分:0)

您应该将true作为构造函数中的第二个参数传递:new Command(script, true)。它告诉该命令是脚本代码,而不是命令名。

以下是代码的PowerShell模拟代码:

# This script calls the external command (cmd) with passed in parameter
$script = @'
param
(
    [parameter(Mandatory=$true,ValueFromPipeline=$true)]
    [string]$installPath
)

cmd /c echo $installPath
'@

# Note: the second parameter $true tells that the command is a script code, not just a command name
$command = New-Object Management.Automation.Runspaces.Command $script, $true
$param = New-Object Management.Automation.Runspaces.CommandParameter "installPath", "C:\UTIL\INSTALL"
$command.Parameters.Add($param)

$rs = [Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace()
$rs.Open()
$pipeline = $rs.CreatePipeline()
$pipeline.Commands.Add($command)
$pipeline.Invoke()

它打印(在控制台主机中):

C:\UTIL\INSTALL