Я использую PS 2.0, VS2010, C# для вызова сценариев Powershell (файлы ps1) с использованием C#.HostException, выполняющий скрипт Powershell с использованием C#
У меня есть этот модульное тестирование и работает отлично:
output = UsingPowerShell(@".\test1.ps1, "");
Assert.IsTrue(output.Contains("StringToBeVerifiedInAUnitTest"));
содержание сценария:
=================== test1.ps1 ==========================
$someVariable = "StringToBeVerifiedInAUnitTest"
$someVariable
=================== End test1.ps1 ==========================
Но этот тест блок выходит из строя. Я получаю сообщение об ошибке:
«не может ссылаться на эту функцию, так как текущий хост не реализует его» содержимое
output = UsingPowerShell(@".\test2.ps1", "");
Assert.IsTrue(output.Contains("test2.ps1"));
Script
=================== 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 метод:
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;
}
Любые предложения?
UPDATE:
Как Windows PowerShell работает
http://msdn.microsoft.com/en-us/library/ms714658(VS.85).aspx
Windows PowerShell работает в рамках размещения приложения (по умолчанию powershell.exe), который предоставляет командную строку для пользователя, и использует интерфейс хоста для связи с командами, вызываемыми командной строкой. Приложение-хостинг может быть консольным приложением, приложением Windows или веб-приложением. В большинстве случаев приложение-хостинг использует свою основную функцию для взаимодействия со средой Windows PowerShell через внутренний интерфейс хоста; однако приложение-хостинг может опционально поддерживать собственный собственный хост, реализуя класс PSHost вместе с одним или несколькими связанными классами пользовательского интерфейса. Вместе эти классы позволяют осуществлять прямую связь между приложением и командами Windows PowerShell.
и другое решение? любой образец для реализации пользовательского PSHost? – Kiquenet
Вы можете написать функцию Write-Host (которая реализует нужные функции) и поместить ее в начало вашего скрипта. –