2012-05-25 1 views
0

Я использую 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.

ответ

1

Write-host не поддерживается хостом powershell, который вы используете.

простой обходной путь заключается в замене:

Write-Host $currentScriptName 
Write-Host `r`nRuta: $scriptDir 

по:

$currentScriptName 
"`r`nRuta: $scriptDir" 
+0

и другое решение? любой образец для реализации пользовательского PSHost? – Kiquenet

+2

Вы можете написать функцию Write-Host (которая реализует нужные функции) и поместить ее в начало вашего скрипта. –