суббота, 25 мая 2013 г.

Выполнение PowerShell в коде программы .Net

Так как powershell и .Net очень близки, то помимо стандартного варианта "вызвать исполняемый файл powershell из кода и передать ему команды", есть и более красивый/умный вариант - через объектную модель PowerShell.

За работу с PowerShell отвечает сборка "System.Management.Automation.dll". Она ставится вместе с SDK или же через NuGet:
Install-Package System.Management.Automation

После этого пишем простенький метод:

   1:  using System.Management.Automation.Runspaces;
   2:  using System.Text;
   3:   
   4:  namespace PowerShell
   5:  {
   6:      public class PowerShellInterpreter
   7:      {
   8:          public string Execute(string command)
   9:          {
  10:              var runspace = RunspaceFactory.CreateRunspace();
  11:              var executeResult = new StringBuilder();
  12:              try
  13:              {
  14:                  runspace.Open();
  15:   
  16:                  var pipeline = runspace.CreatePipeline();
  17:                  pipeline.Commands.AddScript(command);
  18:   
  19:                  var result = pipeline.Invoke();
  20:                  foreach (var psObject in result)
  21:                  {
  22:                      executeResult.AppendLine(psObject.ToString());
  23:                  }
  24:              }
  25:              finally
  26:              {
  27:                  runspace.Close();
  28:              }
  29:              return executeResult.ToString();
  30:          }
  31:      }
  32:  }

Сначала мы создаём "Runspace" - это что-то типа инстанса powershell в памяти, который может обрабатывать поступающие команды (pipeline). Запихиваем в pipeline команду и просим её выполнить (Invoke), в результате получаем массив PSObject (базовый объект powershell). Результат выполнения команд в PowerShell может быть многострочным, поэтому именно массив, а не один объект. Далее мы эти объекты объединяем в строку и возвращаем результат.

Вот такой код можно используем для проверки:
   1:  using System;
   2:  using Microsoft.VisualStudio.TestTools.UnitTesting;
   3:   
   4:  namespace PowerShell
   5:  {
   6:      [TestClass]
   7:      public class PowerShell
   8:      {
   9:          [TestMethod]
  10:          public void PowerShellExcuteTest()
  11:          {
  12:              var interpreter = new PowerShellInterpreter();
  13:              const string command = "$psversiontable.psversion";
  14:              var result = interpreter.Execute(command);
  15:              const string expected = "3.0\r\n";
  16:   
  17:              Assert.AreEqual(expected, result);
  18:          }
  19:      }
  20:  }

Комментариев нет: