Как запускать PowerShell-скрипты через пакетный файл (.bat)
Быстрые ссылки
- Почему нельзя просто копировать .PS1 и запускать?
- Шаг 1: Запуск двойным кликом
- Шаг 2: Обход ExecutionPolicy
- Шаг 3: Получение прав администратора
- Шаг 4: Отключение пользовательских профилей PowerShell
- Готовые .bat-файлы и рекомендации
Для многих операционных задач переносимость PowerShell-скриптов ограничена по соображениям безопасности. Пакетный (.bat) файл рядом со скриптом позволяет аккуратно обойти ряд ограничений без постоянных модификаций настроек системы. Ниже — подробное руководство с примерами, объяснениями, проверками и практическими рекомендациями.
Почему нельзя просто копировать .PS1 и запускать?
Если целевая система не настроена на безопасный запуск произвольных скриптов, вы столкнётесь с комбинацией проблем:
- PowerShell по умолчанию не ассоциирован с расширением .PS1. Windows часто связывает .ps1 с блокнотом, чтобы избежать случайного запуска вредоносных скриптов двойным кликом.
- ExecutionPolicy по умолчанию запрещает выполнение внешних скриптов. В некоторых версиях Windows политика может полностью блокировать запуск скриптов.
- Для части команд нужны права администратора. Даже если учётная запись — член группы Administrators, UAC предотвращает автоматическое повышение прав.
- У пользователя может быть кастомный профиль PowerShell, который меняет среду выполнения (переменные, функции, алиасы) и нарушает поведение скрипта.
Эти ограничения важны для безопасности. Мы решаем их локально для временной сессии, не меняя глобальные настройки ОС.
Шаг 1: Запуск двойным кликом
Проблема с ассоциацией .ps1 решается просто: вы запускаете .bat файл двойным кликом. Батник вызывает PowerShell и передаёт путь к .ps1. Чтобы .bat не пересобирать под каждый скрипт, используем самоссылочную переменную %~dpn0, которая даёт диск, путь и имя файла без расширения.
Требование: .bat и .ps1 должны лежать в одном каталоге и иметь одинаковое имя (например, MyScript.bat и MyScript.ps1).
Простейший пример батника:
@ECHO OFF
PowerShell.exe -Command "& '%~dpn0.ps1'"
PAUSEРазбор строк:
- @ECHO OFF — отключает отображение команд в окне CMD. Символ @ скрывает саму строку.
- PowerShell.exe -Command “& ‘%~dpn0.ps1’” — запускает PowerShell и даёт команду выполнить скрипт по пути, вычисляемому через %~dpn0.ps1.
- PAUSE — ждёт нажатия клавиши, чтобы окно не закрывалось сразу и вы могли увидеть вывод.
Пример сценария и запуска: предположим, что батник и скрипт лежат в D:\Script Lab\MyScript.*. При двойном клике откроется окно PowerShell и будет предпринята попытка выполнить MyScript.ps1.

Примечание: если на машине действует строгая ExecutionPolicy или файл помечен как «загруженный из Интернета», базового батника может быть недостаточно.
Демонстрация проблем при простом запуске
Запустив базовый батник, вы можете увидеть ошибки и подсказки, которые укажут на причину неудачи:

Ключевые наблюдения из этого вывода:
- Окно заголовка показывает, что батник успешно вызвал PowerShell.
- Первая строка вывода сообщает о пользовательском профиле PowerShell — потенциальная проблема №4.
- Появилась ошибка ExecutionPolicy — проблема №2.
- Подчёркнутый фрагмент указывает на целевой путь D:\Script Lab\MyScript.ps1 — значит, батник правильно вычисляет путь к скрипту.
Если хотите воспроизвести поведение профиля, добавьте в свой профиль PowerShell строку:
Write-Output 'Custom PowerShell profile in effect!'Чтобы пометить файл как пришедший извне (для теста ExecutionPolicy), можно добавить Alternate Data Stream Zone.Identifier:
Add-Content -Path 'D:\Script Lab\MyScript.ps1' -Value "[ZoneTransfer]`nZoneId=3" -Stream 'Zone.Identifier'И удалить метку так:
Clear-Content -Path 'D:\Script Lab\MyScript.ps1' -Stream 'Zone.Identifier'Шаг 2: Обход ExecutionPolicy
ExecutionPolicy можно изменить только для текущего запуска PowerShell. Это безопасно: вы не меняете глобальные настройки системы, а лишь указываете параметр для новой сессии.
Обновлённая строка в батнике:
PowerShell.exe -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'"- -ExecutionPolicy Bypass позволяет запустить скрипт в новой сессии, игнорируя политику для этого запуска. Изменение действует только для этой запуска.
После этого вы должны получить выполнение скрипта и увидеть его вывод (но возможно всё ещё без повышения привилегий):

На изображении видно, что скрипт работает, но сообщает, что выполняется в ограниченной сессии. В демонстрационном примере проверка прав делается так:
if (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{Write-Output 'Running as Administrator!'} else {Write-Output 'Running Limited!'}
PauseОбратите внимание: теперь на выводе иногда может быть две паузы — одна из PowerShell-скрипта и одна из батника. Это важно при следующем шаге.
Шаг 3: Получение прав администратора
Если ваш скрипт использует команды, требующие elevation (например, управление службами, редактирование реестра в HKLM, установка программ), нужно запустить PowerShell с правами администратора. Batch/ CMD не умеют инициировать UAC. Но PowerShell умеет через Start-Process с -Verb RunAs.
Идея: первый PowerShell, запущенный батником, вызывает Start-Process для запуска второго PowerShell с -Verb RunAs. Второй экземпляр выполняет .ps1. Получается две сессии: первая инициирует UAC, вторая — исполняет скрипт уже с повышенными правами.
Строка для батника с запуском через UAC:
PowerShell.exe -Command "& {Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass -File ""%~dpn0.ps1""' -Verb RunAs}"Пояснения:
- Start-Process PowerShell.exe — запускает новый процесс PowerShell.
- -ArgumentList содержит параметры для нового процесса: запускаем с -ExecutionPolicy Bypass и указываем -File “%~dpn0.ps1” (двойные кавычки экранированы для корректной передачи).
- -Verb RunAs инициирует UAC. Если текущая сессия не elevated, появится запрос на повышение.
Поведение при запуске:
- Откроется окно PowerShell (первое). Его профиль выполнится.
- Появится UAC-подтверждение. После одобрения запустится новый экземпляр PowerShell — второй процесс.
- Во втором окне тоже выполняется профиль (если вы не отключили профиль) и затем сам скрипт.

После подтверждения вы увидите повышенный сеанс и вывод скрипта:

Почему две паузы? Первая пауза — в теле .ps1 (чтобы пользователь увидел вывод скрипта, пока второй seance открыт). Вторая — в батнике — чтобы вы могли увидеть, что первый запуск PowerShell вообще стартовал, и если запуск второго процесса не удался, увидеть сообщение об ошибке.
Важно: подтверждение UAC запрашивается в контексте текущего пользователя. Если требуется запуск под другой учётной записью, потребуются другие подходы (например, запуск через планировщик задач с сохранёнными учётными данными или использование PSExec/RunAs с учётной записью администратора). Эти методы имеют свои риски и требования безопасности.
Шаг 4: Отключение пользовательских профилей PowerShell
Пользовательские профили PowerShell (файлы profile.ps1) могут менять среду выполнения: создавать алиасы, определять функции, переопределять команды. Чтобы скрипт работал предсказуемо, удобнее запускать PowerShell с ключом -NoProfile.
Измените строку батника так, чтобы оба процесса PowerShell запускались с -NoProfile:
PowerShell.exe -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%~dpn0.ps1""' -Verb RunAs}"Если вам не нужен запрос на повышение прав (шаг 3 пропущен), тогда достаточно одной инстанции PowerShell, и строка будет проще:
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'"Пример вывода для случая без профиля:

Теперь кастомные скрипты профиля не мешают работе, среда более предсказуема, и вы видите только вывод вашего .ps1.
Готовые .bat-файлы
Без повышения прав (подходит для скриптов, не требующих администратора):
@ECHO OFF
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'"
PAUSEС повышением прав через UAC:
@ECHO OFF
PowerShell.exe -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%~dpn0.ps1""' -Verb RunAs}"
PAUSEСоветы по использованию:
- Держите .bat и .ps1 вместе и давайте им одно имя. Так %~dpn0 всегда будет указывать на корректный скрипт.
- Не запрашивайте права администратора, если они не нужны. Минимизируйте поверхность атаки.
- Для распространения скриптов в организации используйте подписанные скрипты и централизованное управление (GPO, Intune), а не постоянные обходы ExecutionPolicy.
Контрпримеры и ситуации, когда этот подход не работает
- ExecutionPolicy на уровне Group Policy может запрещать локальные обходы. Политики, установленные через GPO, могут игнорировать ключи запуска.
- На защищённых системах с ограничёнными правами на запуск исполняемых файлов администрация может блокировать вызов PowerShell.exe вообще.
- Если политика безопасности запрещает интерактивный UAC (например, автоматизированные контейнерные среды), метод с -Verb RunAs не сработает.
- Если файл .ps1 защищён цифровой подписью и организация требует подпись для запуска, временный Bypass может быть запрещён.
Альтернативные подходы
- Создать ярлык (.lnk) с целевой командой: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File “C:\Path\MyScript.ps1”. Ярлык можно запускать двойным кликом и задать запуск от имени администратора в свойствах ярлыка.
- Подписывать скрипты и настроить доверенные издатели — безопасный корпоративный подход.
- Использовать менеджеры конфигурации (SCCM, Intune) для централизованного развертывания и запуска скриптов с требуемыми привилегиями.
- Упаковать утилиту как исполняемый файл с помощью инструментов вроде PS2EXE — это упрощает запуск конечными пользователями, но меняет модель распространения и может вызвать дополнительные сигнатуры AV.
Ментальные модели и эвристики
- Think in layers (слои безопасности): батник лишь временно меняет поведение на уровень сессии. Он не «ломает» глобальную безопасность.
- Principle of least privilege: запрашивайте права администратора только если действительно нужно.
- Predictability first: отключение профилей делает среду выполнения предсказуемой.
Чек-лист ролей
Для разработчика-скриптописателя:
- Назвать .bat и .ps1 одинаково и положить в одну папку.
- Добавить PAUSE для отладки, убрать в релизе, если нужно.
- Использовать -NoProfile и -ExecutionPolicy Bypass по необходимости.
- Документировать, зачем требуются права администратора.
Для администратора:
- Проверить GPO, запрещающие локальные обходы ExecutionPolicy.
- Рассмотреть альтернативы: подпись скриптов, централизованный запуск.
- Обучить сотрудников безопасному использованию.
Для конечного пользователя:
- Двойной клик по .bat запускает скрипт безопасно.
- Подтвердить UAC, если требуется.
- Сообщать разработчику об ошибках и о странном поведении после запуска.
Шпаргалка (cheat sheet) — часто используемые флаги
- -NoProfile — не загружать пользовательские профили PowerShell.
- -ExecutionPolicy Bypass — обойти политику исполнения для текущего запуска.
- -Command “& ‘
.ps1’” — выполнить команду/скрипт в PowerShell. - -File “
.ps1” — передать файл для выполнения. - Start-Process -Verb RunAs — вызвать запуск с запросом UAC.
- %~dpn0 — диск, путь и имя текущего батника без расширения.
Мини-методология развёртывания скриптов в организации
- Разработайте и протестируйте локально с -NoProfile и -ExecutionPolicy Bypass.
- Подпишите скрипты цифровой подписью для корпоративного распределения.
- Если подпись невозможна, используйте защищённые каналы и централизованный запуск (Intune, SCCM).
- Документируйте требования для администраторов и конечных пользователей.
- Логируйте выполнение и результаты команд для аудита.
Критерии приёмки
- Скрипт запускается двойным кликом на тестовой машине без изменения глобальных настроек.
- При необходимости запрашивается UAC и скрипт выполняется с повышенными правами.
- Скрипт выполняется в среде без пользовательских профилей, если это необходимо.
- Вывод виден пользователю до закрытия окна.
Тестовые случаи и приемочные сценарии
- Запуск на чистой машине с дефолтной ExecutionPolicy: батник должен либо корректно запустить скрипт (с Bypass), либо отобразить понятную ошибку.
- Файл помечен Zone.Identifier (импорт из Интернета): батник с -ExecutionPolicy Bypass должен выполнить скрипт.
- Скрипт, требующий администратора: батник с Start-Process и -Verb RunAs должен запросить UAC и выполнить скрипт с правами.
- Пользовательский профиль содержит переопределённые команды: запуск с -NoProfile должен игнорировать профиль и вернуть предсказуемый вывод.
Безопасность и соответствие требованиям конфиденциальности
Важно помнить:
- Обход ExecutionPolicy не отменяет необходимость проверять содержимое скрипта. Всегда проверяйте скрипты на предмет нежелательных действий.
- Не используйте обходы как «постоянное решение» для множества машин. Для организации правильнее — подписывать скрипты и управлять политиками централизованно.
- Если скрипт обрабатывает персональные данные, обеспечьте соответствие локальным требованиям по защите данных (например, GDPR). Логируйте доступы и минимизируйте сбор данных.
Готовые шаблоны и примеры
Шаблон «для разработчика» (без повышения прав):
@ECHO OFF
:: MyScript.bat — запускает MyScript.ps1 в той же папке
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'"
PAUSEШаблон «для конечного пользователя» (с UAC):
@ECHO OFF
:: MyScript.bat — запрашивает повышение прав и запускает MyScript.ps1
PowerShell.exe -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%~dpn0.ps1""' -Verb RunAs}"
PAUSEЕсли вы хотите ярлык вместо батника, целевая команда ярлыка может быть такой:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\Path\MyScript.ps1"1-строчный глоссарий
- ExecutionPolicy — механизм PowerShell, ограничивающий запуск скриптов по происхождению и подписи.
- UAC — User Account Control, механизм Windows для согласования повышения прав.
- %~dpn0 — переменная batch-файла: диск + путь + имя файла (без расширения).
- -NoProfile — ключ PowerShell, запрещающий загрузку пользовательских profile.ps1.
Заключение
Использование простого .bat-файла рядом с .ps1 даёт удобный и контролируемый способ запускать PowerShell-скрипты на компьютерах, где вы не хотите или не можете менять глобальные настройки системы. Такой подход сохраняет безопасность системы и даёт пользователям удобный двойной щелчок для запуска. Для корпоративного распространения рассмотрите подпись скриптов и централизованное управление политиками.
Важно: всегда проверяйте скрипты перед запуском и минимизируйте запросы прав администратора.
Справочные материалы:
- Running PowerShell scripts from a batch file — Daniel Schroeder’s Programming Blog
- Checking for Administrator permissions in PowerShell — Hey, Scripting Guy! Blog
Похожие материалы
Блокировать и отключать SMS на iPhone
Доступ к файлам Android в Проводнике Windows по Wi‑Fi
Использовать iPhone как USB‑накопитель
Как создать профиль Kids на Google TV
Cortex: быстро делиться контентом в соцсетях