2012-05-25 7 views
0

C#을 사용하여 Powershell 스크립트 (ps1 파일)를 호출 할 때 PS 2.0, VS2010, C#을 사용합니다.C#을 사용하여 Powershell 스크립트를 실행하는 HostException

나는이 단위 테스트를하고 잘 작동 :

output = UsingPowerShell(@".\test1.ps1, ""); 
Assert.IsTrue(output.Contains("StringToBeVerifiedInAUnitTest")); 

스크립트 내용 :

=================== test1.ps1 ========================== 
$someVariable = "StringToBeVerifiedInAUnitTest" 
$someVariable 
=================== End test1.ps1 ========================== 

그러나이 단위 테스트가 실패합니다.

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; 

     } 
:

 output = UsingPowerShell(@".\test2.ps1", ""); 
     Assert.IsTrue(output.Contains("test2.ps1")); 

스크립트 내용

=================== 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 방법

는 "현재 호스트가 구현하지 않기 때문에이 함수를 호출 할 수 없습니다":이 오류 메시지가

의견이 있습니까?

UPDATE :

방법의 Windows PowerShell이 ​​작동
http://msdn.microsoft.com/en-us/library/ms714658(VS.85).aspx

Windows PowerShell을 사용자에게 명령 줄을 노출하는 호스팅 응용 프로그램 (기본값하여 powershell.exe입니다) 내에서 작동하고, 호스트 인터페이스를 사용

명령 줄에서 호출 한 명령과 통신합니다. 호스팅 응용 프로그램은 콘솔 응용 프로그램, Windows 응용 프로그램 또는 웹 응용 프로그램이 될 수 있습니다. 대부분의 경우 호스팅 응용 프로그램은 Main 함수를 사용하여 내부 호스트 인터페이스를 통해 Windows PowerShell 런타임과 상호 작용합니다. 그러나 호스팅 응용 프로그램은 하나 이상의 관련 사용자 인터페이스 클래스와 함께 PSHost 클래스를 구현하여 자체 사용자 지정 호스트를 선택적으로 지원할 수 있습니다. 이러한 클래스를 함께 사용하면 응용 프로그램과 Windows PowerShell 명령을 직접 통신 할 수 있습니다.

답변

1

쓰기 호스트는 사용중인 PowerShell 호스트에서 지원되지 않습니다.

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

에 의해 :

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

및 기타 솔루션

쉬운 해결 방법은 대체 무엇입니까? 사용자 지정 PSHost를 구현하기위한 샘플은 무엇입니까? – Kiquenet

+2

Write-Host (원하는 기능을 구현하는) 함수를 작성하여 스크립트 상단에 배치 할 수 있습니다. –

관련 문제