Привет, Хабр! 

Меня зовут Денис, я ведущий специалист в отделе информационной безопасности компании «Совкомбанк Технологии». Наша команда занимается поддержкой работы антивируса, программ для сбора логов на конечных точках и другими задачами в области ИБ.

В каждой ИТ-команде рано или поздно появляется свой набор скриптов, и у каждого сотрудника он может быть индивидуальный: у кого-то — волшебный .ps1-файл для быстрого развёртывания или сбора информации из сети, у кого-то — личная палочка-выручалочка для генерации отчётов. Наша команда не стала исключением. Были и общие скрипты, и личные «шедевры», передаваемые из рук в руки. Эти инструменты экономили часы работы — но только для тех, кто знал, какие параметры подавать на вход скрипта, где лежит актуальная версия скрипта и так далее. Стало ясно, что необходимо объединить их для более эффективного выполнения рутинных задач, и этим решением стал GUI, о чём мы поговорим в статье.

Это руководство пригодится всем, кто устал от рутины и хочет сделать свои PowerShell-скрипты доступными для коллег: системным администраторам, инженерам технической поддержки, DevOps-специалистам.

Мы не только разберем основы создания кнопок и окон, но и ответим на ключевые вопросы: Как выбрать между WinForms и WPF, как избежать зависания интерфейса при выполнении долгих операций, и как удобно упаковать ваш скрипт в EXE или ярлык, чтобы любой сотрудник мог запустить его одним кликом.

Графический интерфейс как решение

Переломный момент наступил, когда я задал себе вопрос: «Почему скрипт обязательно должен быть в консоли?». Почему бы не превратить его в удобное приложение с кнопками, подсказками и прогресс-барами, которое будет понятно каждому? Я начал внедрять графические интерфейсы на PowerShell — и это изменило всё. Скрипты перестали быть «чёрными ящиками», доступными только избранным. Они стали инструментами команды: обновляемыми, надёжными и интуитивно понятными. И каждый может ими воспользоваться — просто нажав кнопку. 

Windows Forms или WPF: какой интерфейс выбрать и когда?

Для реализации графического интерфейса GUI в PowerShell доступны два основных подхода: 

  1. Windows Forms — проверенная, но уже устаревшая технология, главное преимущество которой — простота использования. 

  2. WPF — более современное и гибкое решение, позволяющее создавать продвинутые интерфейсы, но требующее изучения основ. 

Сравнительная таблица

Критерий

Windows Forms

WPF

Сложность

Прост в освоении, минимальный порог входа

Требует изучения XAML и новых концепций

Современность

Устаревшая технология

Актуальная, поддерживает современные стандарты

Дизайн

Устаревший, но функциональный

Современный, с анимациями

Поддержка

Работает даже на Windows 7

Требует .NET 3.0+

Гибкость

Ограниченная кастомизация

Полный контроль над интерфейсом

Быстрый старт: PowerShell + GUI

Windows Forms

Add-Type -AssemblyName System.Windows.Forms  
# Создаем форму
$form = New-Object System.Windows.Forms.Form
$form.Text = "Пример WinForms"
$form.Size = New-Object System.Drawing.Size(300, 200)
# Добавляем кнопку
$button = New-Object System.Windows.Forms.Button
$button.Text = "Нажми меня"
$button.Location = New-Object System.Drawing.Point(100, 50)
$button.Add_Click({ [System.Windows.Forms.MessageBox]::Show("Привет, WinForms!") })
# Добавляем элементы на форму
$form.Controls.Add($button)
# Показываем форму
$form.ShowDialog() | Out-Null

WPF (без XAML)

Add-Type -AssemblyName PresentationFramework  
# Создаем окно
$window = New-Object System.Windows.Window
$window.Title = "Пример WPF"
$window.Width = 300
$window.Height = 200
# Создаем кнопку
$button = New-Object System.Windows.Controls.Button
$button.Content = "Нажми меня"
$button.Add_Click({ [System.Windows.MessageBox]::Show("Привет, WPF!") })
# Добавляем кнопку в окно
$window.Content = $button
# Показываем окно
$window.ShowDialog() | Out-Null

WPF с XAML (рекомендуется для сложных интерфейсов)

Add-Type -AssemblyName PresentationCore, PresentationFramework
# XAML-разметка (у кнопки есть имя "MyButton")
$xaml = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WPF с XAML" Width="300" Height="200">
    <Button x:Name="MyButton" Content="Нажми меня" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Window>
"@
# Загружаем XAML
$reader = [System.Xml.XmlReader]::Create([System.IO.StringReader]::new($xaml))
$window = [Windows.Markup.XamlReader]::Load($reader)
# Находим кнопку по имени и добавляем действие
$button = $window.FindName("MyButton")
$button.Add_Click({  [System.Windows.MessageBox]::Show("XAML работает!", "Успех") })
# Показываем окно
$window.ShowDialog() | Out-Null

Оптимизация работы скриптов: как избежать зависания интерфейса

Когда в графическом интерфейсе запускаются ресурсоёмкие скрипты, интерфейс может перестать реагировать. Это происходит потому, что основной поток занят вычислениями и не обрабатывает действия пользователя.

Решение: фоновые задачи с Start-ThreadJob

Командлет Start-ThreadJob позволяет выполнять скрипты в отдельном потоке, сохраняя отзывчивость интерфейса. 

Пример для WPF: 

Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName WindowsBase

# Создаем окно в XAML
[xml]$xaml = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        Title="Фоновая задача в WPF" Height="200" Width="300">
    <StackPanel VerticalAlignment="Center">
        <ProgressBar Name="ProgressBar" Height="20" Margin="10" Minimum="0" Maximum="100"/>
        <Button Name="StartButton" Content="Запустить задачу" Margin="10"/>
    </StackPanel>
</Window>
"@

# Загружаем XAML
$reader = [System.Xml.XmlNodeReader]::new($xaml)
$window = [Windows.Markup.XamlReader]::Load($reader)
$progressBar = $window.FindName("ProgressBar")
$startButton = $window.FindName("StartButton")

# Запуск фоновой задачи
$startButton.Add_Click({
    Start-ThreadJob  -ScriptBlock {
        $window = $using:window
        $progressBar = $using:progressBar
        foreach($i in 1..100 ){
            if($i -eq 50){
                $window.Dispatcher.Invoke([action]{
                $progressBar.Value = $i
                },"Normal") 
            }
            if($i -eq 100){
                $window.Dispatcher.Invoke([action]{
                $progressBar.Value = $i
                },"Normal")
            }
        }
        
    }

})

$window.ShowDialog() 

Примечание:

Start-ThreadJob — доступен только в PowerShell 7+. Для версий 5.1 и ниже используйте Runspaces или комбинацию Register-ObjectEvent с Start-Job.

Оптимальные способы запуска PowerShell-скриптов

При распространении скриптов внутри компании всегда важно не забывать о цифровой подписи скриптов,если политики безопасности это требуют.

Для удобства пользователей можно выбрать один из двух подходов:

Конвертация PS1 в EXE (с помощью PS2EXE)

Install-Module -Name ps2exe -Force

Invoke-PS2EXE-InputFile"ваш_скрипт.ps1"-OutputFile"приложение.exe"-NoConsole-IconFile"иконка.ico" 

Плюсы:

  • Автономность – не требует PowerShell вручную

  • Защита кода – но не полная

Минусы: 

- Антивирусы могут блокировать такие EXE-файлы. 

2. Создание ярлыка

Плюсы:

  • Простота и быстрое обновление. 

  • Не требует пересборки при изменениях скрипта. 

Как настроить:

  1. Создайте ярлык. 

  2. В поле «Расположение объекта» укажите: 

    powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden –File "путь к скрипту "
  3. Добавьте иконку через свойства ярлыка. 

Заключение

PowerShell — это не просто командная строка, а мощный инструмент для создания удобных и функциональных интерфейсов. С его помощью можно: 

  • Превращать сложные скрипты в простые приложения. 

  • Интегрироваться с API и внутренними системами. 

  • Автоматизировать рутину, экономя часы работы. 

Главный результат? Раньше наши скрипты напоминали священные свитки — ценные, но доступные лишь избранным. Теперь это рабочие инструменты, которые: 

  • Ломают барьеры между разработчиками и пользователями. 

  • Синхронизируют команду (никаких «у меня другая версия»). 

  • Превращают сложное в простое. 

По факту, мы не просто автоматизировали процессы — мы изменили культуру работы. 

А как у вас? Объединяет ли автоматизация вашу команду или, наоборот, создаёт барьеры? 

Совет: Начните с одной задачи, добейтесь успеха — и масштабируйте решение. PowerShell GUI тем и хорош, что растёт вместе с вашими потребностями. 

Удачи в автоматизации!  

Комментарии (1)


  1. Andrei9385
    14.11.2025 13:42

    Раньше тоже писал формы на Powershell, Windows Forms и WPF, потом стал писать с ИИ на IIS, с доступом через вэб интерфейс. ИИ успешно с этим справляется, доступ ко всем сервисам из одной точки, Kerberos аутентификация. Это более универсальный метод и формы можно красивые и гибкие делать.