I use PS 2.0, VS2010, C# for call Powershell scripts (ps1 files) using C#.
I have this Unit Test and works fine:
output = UsingPowerShell(@".\test1.ps1, "");
Assert.IsTrue(output.Contains("StringToBeVerifiedInAUnitTest"));
Script contents:
=================== test1.ps1 ==========================
$someVariable = "StringToBeVerifiedInAUnitTest"
$someVariable
=================== End test1.ps1 ==========================
But this Unit test fails. I get this error message:
"Cannot invoke this function because the current host does not implement it”
output = UsingPowerShell(@".\test2.ps1", "");
Assert.IsTrue(output.Contains("test2.ps1"));
Script contents
=================== test2.ps1 ==========================
$fullPathIncFileName = $MyInvocation.MyCommand.Definition
$currentPath = $MyInvocation.MyCommand.Path
$currentScriptName = $MyInvocation.MyCommand.Name
$currentExecutingPath = $fullPathIncFileName.Replace($currentScriptName, "")
$scriptDir = Split-Path -parent $MyInvocation.MyCommand.Path
#Write-Host $currentExecutingPath
Write-Host $currentScriptName
Write-Host `r`nRuta: $scriptDir
=================== End test2.ps1 ==========================
UsingPowerShell method:
public static string UsingPowerShell(string scriptPS, string parametros)
{
if (string.IsNullOrWhiteSpace(parametros)) return UsingPowerShell(scriptPS, new List<string> { });
return UsingPowerShell(scriptPS, parametros.Split(' '));
}
public static string UsingPowerShell(string scriptPS, IList<string> parametros)
{
var builder = new StringBuilder();
string answer = null;
RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
InitialSessionState iss = InitialSessionState.CreateDefault();
using (Runspace runspace = RunspaceFactory.CreateRunspace(iss))
{
runspace.Open();
//runspace.ApartmentState = System.Threading.ApartmentState.STA;
//runspace.ThreadOptions = PSThreadOptions.UseCurrentThread;
RunspaceInvoke runSpaceInvoker = new RunspaceInvoke(runspace);
runSpaceInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
// create a pipeline and feed it the script text
using (Pipeline pipeline = runspace.CreatePipeline())
{
Command command = new Command(scriptPS,true,true);
foreach (var param in parametros)
{
command.Parameters.Add(null, param);
}
pipeline.Commands.Add(command);
//pipeline.Commands.AddScript(cmdArg);
//runspace.SessionStateProxy.SetVariable("MyResponse", response);
pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
Collection<PSObject> psresults = pipeline.Invoke();
//PSObject newResponse = (PSObject)runspace.SessionStateProxy.GetVariable("MyResponse");
//if you want to get a value from a variable in you script like so:
//Object resultcollection = runspace.SessionStateProxy.GetVariable("results");
// convert the script result into a single string
var sb = new StringBuilder();
foreach (PSObject obj in psresults)
{
sb.AppendLine(obj.ToString());
}
answer = sb.ToString();
Console.WriteLine(answer);
//Console.WriteLine(psresults.ToArray()[0].ToString());
// check for errors (non-terminating)
if (pipeline.Error.Count > 0)
{
//iterate over Error PipeLine until end
while (!pipeline.Error.EndOfPipeline)
{
//read one PSObject off the pipeline
var value = pipeline.Error.Read() as PSObject;
if (value != null)
{
//get the ErrorRecord
var r = value.BaseObject as ErrorRecord;
if (r != null)
{
//build whatever kind of message your want
builder.AppendLine(r.InvocationInfo.MyCommand.Name + " : " + r.Exception.Message);
builder.AppendLine(r.InvocationInfo.PositionMessage);
builder.AppendLine(string.Format("+ CategoryInfo: {0}", r.CategoryInfo));
builder.AppendLine(string.Format("+ FullyQualifiedErrorId: {0}", r.FullyQualifiedErrorId));
}
}
}
//return builder.ToString();
}
pipeline.Dispose();
}
runspace.Close();
}
return answer;
}
Any suggestions?
UPDATE:
How Windows PowerShell Works
http://msdn.microsoft.com/en-us/library/ms714658(VS.85).aspx
Windows PowerShell operates within a hosting application (the default is powershell.exe) that exposes a command line to the user, and uses a host interface to communicate with the commands invoked by the command line. The hosting application can be a console application, a Windows application, or a Web application. In most cases, the hosting application uses its Main function to interact with the Windows PowerShell runtime through the internal host interface; however, a hosting application can optionally support its own custom host by implementing the PSHost class along with one or more related user interface classes. Together, these classes allow direct communication between the application and Windows PowerShell commands.