2017-01-09 5 views
0

Lync/S4f/Exchange 서버에서 원격 powershell을 실행하고 있습니다. 동기 작업은 모두 정상적으로 작동하지만 비공식으로 변환하는로드 블록이 발생했습니다.Powershell 원격 파이프 라인에서 Pipeline.AsyncInvoke

RunSpace가 표준 BeginOpen/EndOpen 및 BeginClose/EndClose 작업을 제공하기 때문에 연결/연결 비동기를 만들지 만 InvokeAsync는 void 유형입니다. 여기

내 코드입니다 (에서 ConnectionInfo는

new Uri("https://" + config.Server + "/ocspowershell") 

을 다음과 그리고 이것은 실제 원격 실행 코드 여기

Runspace myRunSpace = RunspaceFactory.CreateRunspace(connectionInfo); 
myRunSpace.Open(); 
using (Pipeline pipeLine = myRunSpace.CreatePipeline()) 
{ 
    Command myCommand = new Command("Get-CsArchivingPolicy"); 
    pipeLine.Commands.Add(myCommand); 
    pipeLine.StateChanged += PipeLine_StateChanged; 
    waiter = new TaskCompletionSource<Collection<PSObject>>(); 
    pipeLine.Error.DataReady += Error_DataReady; 
    pipeLine.Output.DataReady += Output_DataReady; 
    pipeLine.InvokeAsync(); 
    pipeLine.Input.Close(); 
    await waiter.Task.ConfigureAwait(false); 
} 

그대로 URI 세트를 가지고 WSManConnectionInfo 내가 ..보고 만약있어 무엇이다 입력을 닫지 않고 실행중인 상태가 아닌 파이프 라인이 실행됩니다.

입력을 닫는 즉시 Error_DataReady 0 개의 항목을 읽고 EndOfPipeline을 true로 설정하면 EndOfPipeline이 true이지만 Count도 0이되므로 Output_DataReady를 얻습니다. 따라서 Reader에서 Read를 호출해도 작동하지 않습니다.

그러면 파이프 라인이 완료 됨 상태가됩니다. 그래서 .. 명령이 실행됩니다 .. 그러나 출력은 어디 있습니까?

내가 파이프 라인을 수행하면. 내 결과로 멋진 콜렉션을 얻을 수 있습니다 .. 그래서 명령이 정확하다는 것을 압니다. 하지만 비동기 모드에서 실행할 때 출력과 관련하여 뭔가 빠져 있어야합니다.

+0

Exchange'pipeLine.Input.Close();'와'pipeLine.InvokeAsync();'. – PetSerAl

+0

실행이가는 한 그 속임수는 ... 하지만 reder.Read (reader.Count = PipelineReader 에서 Output_DataReady에서 가져온 메서드는 항상 메소드가 지원되지 않는다는 예외를 throw합니다 (reader.ReadToEnd에서도 마찬가지입니다). 어떻게하면 올바르게 알지 못할 것입니다. 결과를 읽으시겠습니까? – user3566056

답변

0

비동기 처리를 수행하는 다른 방법을 찾았습니다.

  using (PowerShell ps = PowerShell.Create()) 
      { 
       if (remoteRunspacePool != null) 
        ps.RunspacePool = remoteRunspacePool; 
       else 
        ps.Runspace = remoteRunSpace; 
       Command myCommand = new Command(getPolicyExtractionCommand(dummy)); 
       Command myCommand2 = new Command("Select-Object"); 
       ps.Commands.AddCommand(myCommand); 
       var props = new string[] { "Identity", "Description", "Name" }; 
       myCommand2.Parameters.Add("Property", getPropertiesForPolicies(dummy)); 
       ps.Commands.AddCommand(myCommand2); 

       PSDataCollection<PSObject> execRes = await Task.Factory.FromAsync(beingRes, ps.EndInvoke).ConfigureAwait(false); 
       Collection<PSObject> processes = execRes.ReadAll(); 
      } 

아이디어는 Invoke에 대한 오래된 구식 비동기 비동기 시작 및 종료 메서드가있는 PowerShell 클래스를 사용하는 것입니다. 그런 다음 TAP을 사용하여 이것을 현대식 비동기 실행으로 바꿀 수 있습니다.

이전에 설정 한 runspace가있는 경우 (이전 예제처럼) PowerShell 인스턴스에 할당 할 수 있습니다. 또한 RunspacePool (IAsyncresult 스타일의 열기 및 닫기 메서드를 지원함)과도 작동합니다. 불행하게도 Runspace의 OpenAsync와 CloseAsync는 다시 상태 변경 (StateChanged 이벤트 연결, OpenAsync 호출, 오류 대기 또는 상태 열기, 실행 계속)을 기다려야하는 이상한 구성으로 만들어집니다.

IMHO Microsoft는 PowerShell에 대해 좀 더 비동기적인 사랑을 보여 주어야합니다.