Trying to execute PowerShell 2.0 script from a .NET installer's custom action
I've been working on this issue for a couple days and have read several posts here, but I can't get my implementation to work. I am calling the powershell script during the Commit custom action. When I get to the pipeline.Invoke() method, I get an exception that says the entire script "is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again."
Here is my script:
Param(
[parameter(Mandatory=$true,ValueFromPipeline=$true)]
[string]$installPath
);
schtasks /create /TN MyTask /RU domain\account /RP password /xml $installPath\MyTaskSchedule.xml;
I've tried it with and without the traili开发者_开发问答ng semi-colons, with and without a wrapping function. I've verified that the C# code is passing the correct install path and that the xml file exists in the directory before this step is hit. I can run this from PowerShell itself and it works just fine.
Here is my code:
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 );
}
}
}
}
When the exception is caught at pipeline.Invoke, the entire script is displayed (with the $installPath instead of the actual path) as a string before the error message detailed above. I've tried several checks within the script itself, but I get the same results no matter what, which tells me that the runspace just doesn't like the script itself.
You should pass true
as the second parameter in the constructor: new Command(script, true)
. It tells that the command is a script code, not a command name.
Here is a working PowerShell analogue of your code:
# 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()
It prints (in the console host):
C:\UTIL\INSTALL
精彩评论