Как использовать PowerShell в C#. Инструкция
В современном мире, где особо ценна скорость и простота управления компьютерными системами, важно не только использовать существующие системы удаленного управления и администрирования, но еще иметь возможность настроить и автоматизировать процессы под себя.
Удаленное администрирование оптимизирует работу компании по нескольким параметрам. Во-первых, это сокращение ФОТ, ведь нужно меньше специалистов для обслуживания даже большой ИТ-инфраструктуры. Во-вторых, исключается человеческий фактор, что уменьшает вероятность ошибок. В-третьих, это позволяет сформировать четкое планирование и выполнение регламентных задач в срок.
В работе нашего сервиса зачастую необходимо использовать подключение к серверам и выполнять удаленное администрирование. Будь то перезапуск пула опубликованной базы либо же администрирование сервера предприятия 1С. Для этих целей мы решили использовать PowerShell.
Windows PowerShell — это оболочка, которая позволяет выполнять команды на языке сценариев.
При помощи PowerShell мы реализуем следующие операции:
- Перезапуск пула опубликованной базы 1С на удаленных серверах публикации с IIS.
- Закрытие открытых файлов информационных баз на удаленных файловых хранилищах.
- Администрирование серверов предприятия 1С через rac/ras.
Использование PowerShell в C# - это расширение возможностей для управления ИТ-инфраструктурой. Применяя PowerShell в своем коде, разработчик получает возможность отказаться от ручного управления в пользу кода.
1. Создание консоли PowerShell
Для доступа к консоли PowerShell необходимо использовать одноименный класс из пространства имен System.Management.Automation.

Прежде чем выполнить какую либо команду, необходимо определить, на какой машине она будет производиться. Это может быть текущая машина, на которой запущена консоль либо же любая другая в сети.
2. Получение разрешения на удаленное управление
Мы используем только удаленное выполнение. В первую очередь на удаленной машине должно быть разрешено удаленное управление. За это в Windows отвечает служба WinRM. Команда для запуска службы выглядит так: `Enable-PSRemoting`. В нашем случае нет необходимости настраивать ее дополнительно, так как все права доступа регулируются контроллером домена.
Далее необходимо подготовить саму консоль PowerShell.

Данный метод добавляет в PowerShell консоль команду вида Invoke-Command -ComputerName Название машины -ScriptBlock { код скрипта }
3. Настройка пространства для выполнения команд
Здесь необходимо создать Runspace.
Runspace - это отдельное пространство выполнения, которые запущено в текущем процессе PowerShell.

Внутри этого пространства и будет выполнен указанный блок скрипта.
Следует учесть,что в таком варианте использования невозможно указать несколько названий машин в параметре -ComputerName. Победить данную проблему нам пока не удалось.
4. Обработка результата выполнения команды
Для запуска команды необходимо выполнить метод powerShell.Invoke(). Он возвращает коллекцию объектов PSObject, с которыми мы и будем работать.
Для проверки наличия ошибок в ходе выполнения необходимо обратиться к полю powerShell.HadErrors. Если это поле имеет значение true, можно прочитать краткое содержимое ошибок выполнения в поле powerShell.Streams.Error. В нем содержится коллекция объектов типа ErrorRecord.
Мы делаем это подобным образом:

Если ошибок не обнаружено, продолжим работу с коллекцией объектов типа PSObject.
Следует учесть, что если скрипт выполнен на удаленной машине, то поле BaseObject объекта PSObject всегда будет равно null.
У каждого объекта есть коллекция объектов типа PSPropertyInfo. К каждому элементу данной коллекции можно обратиться по названию и получить его значение.
Например так:
psProperties["applicationPool"]?.Value
Либо использовать десериализацию подобным образом:
psObject.Properties.DeserializeFromPowerShell<AppPoolStateDc>()
Наш метод расширения DeserializeFromPowerShell устроен так:

Он принимает тип результирующей модели и коллекцию свойств объекта PSObject.
Далее на основании атрибутов DataMember у результирующей модели ищет совпадение в коллекции свойств объекта PSObject, конвертирует и заполняет указанное значение.
Пример результирующей модели состояния пула на сервере публикации

Примеры, как это реализовано у нас
1. Перезапуск пула приложения на IIS
Для перезапуска пула ранее мы использовали класс ServerManager. Но скорость его работы не подходит под наши требования.
Решением было переписать механизм на использование PowerShell.
Перезапуск пула состоит из следующих этапов:
1. Поиск названия пула приложения на IIS по относительному пути публикации
2. Проверка состояния пула на наличие запущенных рабочих процессов w3wp
3. Остановка пула и ожидание остановки
4. Запуск пула и ожидание запуска
Рассмотрим каждый этап
Поиск названия пула
Get-WebApplication -Site "{PublishSiteName}" -Name "{AcDbPublishPath}"
где PublishSiteName - название сайта публикации
AcDbPublishPath - относительный путь публикации.
В результате получаем объект PSObject у которого в свойствах есть поле applicationPool - название пула приложения.
Проверка состояния пула
$appPool = Get-IISAppPool "{AppPoolName}"; [PSCustomObject]@{ AppPoolName = $appPool.Name; PoolState = $appPool.State.ToString(); WorkerProcessesCount = $appPool.WorkerProcesses.Count }
где AppPoolName - название пула приложения, полученное из предыдущего шага.
В результате получаем собственный объект PSObject, в который записываем только необходимые нам значения. А именно название, состояние и количество рабочих процессов.
Остановка пула и ожидание остановки

Данный скрипт запускает остановку пула, ожидает его остановку и ничего не возвращает.
Запуск пула и ожидание запуска

Данный скрипт работает аналогичным образом, как и при остановке.
2. Закрытие открытых файлов информационных баз на удаленных файловых хранилищах
Данная операция нужна для завершения сессий в пользовательских базах 1С.
Выполняется она следующей командой
Get-SmbOpenFile | where {{$_.Path –like \"*{AcDbPath}*\"}} | Close-SmbOpenFile -Force
где AcDbPath - относительный путь к файлам базы 1С.
PowerShell подключается к удаленному файловому хранилищу и выполняет аналогичные действия, как и при ручном закрытии открытых файлов через “Управление компьютером” -> “Общие папки” -> “Открытые файлы”
Большой плюс PowerShell - это простота и удобство использования за счет синтаксиса и возможностей удаленного управления серверами. А интеграция с C# дает хороший прирост в производительности в сравнении с другими утилитами. Мы имеем мощный инструмент для реализации огромного количества задач администрирования. Начиная от перезапуска и конфигурации системы до обеспечения доступа к ресурсам удаленной машины (файлам, папкам, программам).