2017-01-09 3 views
0

Я запускаю удаленную оболочку PowerShell на серверах Lync/S4f/Exchange. Синхронные операции работают нормально, но я попал в блокпост, преобразовывая вещи в async.Pipeline.AsyncInvoke на удаленном трубопроводе Powershell

Мне удалось выполнить асинхронное соединение/разъединение, так как RunSpace предлагает стандартные операции BeginOpen/EndOpen и BeginClose/EndClose, но InvokeAsync имеет тип void.

Вот мой код (connectionInfo является WSManConnectionInfo, который имеет Uri набор следующим

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); 
} 

Вот что я вижу .. Если Я не закрываю вход, ничего не происходит, кроме входа в рабочее состояние.

Как только я закрываю вход, я получаю Error_DataReady с 0 пунктами для чтения и EndOfPipeline является истинным, тогда я получаю Output_DataReady, причем EndOfPipeline имеет значение true, но Count также равен 0 (так что вызов Read on the reader не работает).

Затем трубопровод входит в состояние завершенности. Итак .. команда запускается .. но где же результат?

Если я делаю pipe.Invoke, я получаю хорошую коллекцию с результатами. Поэтому я знаю, что команда верна. Но я должен упускать что-то относительно вывода при работе в асинхронном режиме.

+0

Обмен 'pipeLine.Input.Close();' и 'pipeLine.InvokeAsync();'. – PetSerAl

+0

Это делает трюк .. насколько исполнение идет. Но вызов reder.Read (reader.Count = на PipelineReader , который вы получаете из Output_DataReady, всегда вызывает исключение, говорящее мне, что метод не поддерживается (аналогично для 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(); 
      } 

Идея заключается в том, чтобы использовать класс PowerShell, который имеет свою обычную старую школу асинхр несвежих Begin и методы End для Invoke. Затем, используя TAP, вы можете обернуть это в асинхронное выполнение современного стиля.

Если у вас есть ранее установленная пробел (как в моем предыдущем примере), вы можете назначить его экземпляру PowerShell. Он также работает с RunspacePool (который в перспективе поддерживает методы Open и Close типа IAsyncresult). К сожалению, OpenAsync и CloseAsync в Runspace снова сделаны из этой странной конструкции, где вам нужно ждать изменений статуса (подключить событие StateChanged, вызвать OpenAsync, дождаться ошибки или открыть статус, а затем продолжить выполнение).

IMHO Microsoft должна показать немного больше асинхронной любви к PowerShell.

Смежные вопросы