Powershell, Policy, Bypass, Process, Process Bypass
260728_Alica_Notepad++_VSCode_Powershell_Word_Wordpad_Pdf_RTF_Markdown_.docx
Алиса
Да, это и есть обычный, самый правильный и безопасный способ для разовых задач — именно так и делают в CI/CD и при локальной отладке.
Ты делаешь ровно то, что нужно:
- Меняешь политику только для текущего процесса (
Scope Process) — она живёт, пока открыт этот терминал. - Не трогаешь систему, не требуешь прав админа, не ломаешь настройки на машине.
- Как только терминал закроется — всё вернётся к
LocalMachine: RemoteSigned.
Почему $PSExecutionPolicyPreference пустой — ещё раз, чтобы закрыть этот вопрос
Это не баг и не ошибка. Эта переменная — особенность Windows PowerShell 5.1. В PowerShell 7+ (у тебя 7.6.4) её просто нет: политика для Process хранится внутри рантайма, а не в отдельной переменной. Так что пустое значение — это ожидаемое поведение для твоей версии.
Как это выглядит в реальных сценариях под твой C#‑проект
Сценарий 1: Локальный запуск скрипта деплоя/остановки
Ты в VS Code в терминале pwsh, делаешь:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\deploy.ps1
Скрипт останавливает твой BackgroundService, копирует новую сборку, запускает заново, проверяет health‑check. Всё работает, терминал закрыл — никаких следов.
Сценарий 2: Azure DevOps / GitHub Actions (в пайплайне)
В YAML‑шаге почти всегда пишут именно так:
- powershell: |
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\build.ps1
displayName: 'Build with PowerShell'
Это стандарт индустрии: не менять настройки агента, а включать Bypass только на время шага.
Сценарий 3: Быстрый тест логики с TPL Dataflow
Допустим, ты хочешь проверить, как сервис реагирует на остановку. Пишешь маленький скрипт test-stop.ps1, который:
- Запускает сервис.
- Ждёт N секунд.
- Останавливает процесс.
- Проверяет, что все блоки TPL Dataflow завершили обработку.
И запускаешь его в терминале с Bypass — быстро, изолированно, без лишних настроек.
Важные правила безопасности (чтобы не привыкать к «всё разрешено»)
- Никогда не ставь Bypass на
LocalMachine. Это снимет защиту со всей системы.Scope Process— это золотая середина. - Не делай это в скриптах, которые лежат в репозитории и запускаются у других людей. Пусть каждый сам решает, запускать ли Bypass. Лучше явно писать в README: «Для запуска скриптов нужен Bypass в текущем процессе».
- Для продакшн‑серверов часто вообще не используют скрипты, а ставят сервисы через MSI/MSIX или через готовые задачи CI/CD, где политика уже настроена администратором.
Лайфхак: как не печатать эту команду каждый раз в VS Code
Если ты часто запускаешь свои скрипты в VS Code и надоело каждый раз вводить Set-ExecutionPolicy, можно сделать один из двух вариантов:
Вариант А: Task в VS Code (рекомендуется)
В папке проекта создай .vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"label": "Run Deploy Script",
"type": "shell",
"command": "pwsh",
"args": [
"-NoProfile",
"-ExecutionPolicy", "Bypass",
"-File", "${workspaceFolder}\\deploy.ps1"
],
"problemMatcher": []
}
]
}
Теперь в VS Code нажимаешь Ctrl+Shift+P → «Tasks: Run Task» → «Run Deploy Script», и всё запускается сразу с Bypass. Никаких ручных команд.
Вариант Б: Профиль PowerShell (если только для себя)
Создай (или отредактируй) профиль:
$profile
И добавь туда:
if ($env:VSCODE_INSIDER -eq "true" -or $env:TERM_PROGRAM -eq "vscode") {
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force
}
Но этот вариант менее предсказуемый: он срабатывает при каждом запуске PowerShell в VS Code, и другие люди, открыв твой проект, могут не понять, откуда берётся Bypass. Поэтому для командных проектов лучше Вариант А.
Учитывая, что ты делаешь асинхронный сервис с двухтактной остановкой, такой подход с временным Bypass идеален: ты можешь быстро гонять скрипты проверки остановки, не рискуя безопасностью системы и не усложняя инфраструктуру.
Если скажешь, какой именно скрипт ты планируешь запускать (деплой, тест остановки, проверка логов), я помогу оформить его и задачу в VS Code под этот сценарий. 😊
Я
Алиса
Да, скрипты будут работать — и именно потому, что в колонке Process стоит Bypass.
Почему «почти все Undefined» — это нормально
PowerShell применяет политику по приоритету (от самого локального к самому глобальному). Порядок такой:
- MachinePolicy (через GPO домена)
- UserPolicy (тоже через GPO)
- Process (то, что ты задал вручную в этом сеансе)
- CurrentUser
- LocalMachine
Если на каком‑то уровне значение Undefined, PowerShell просто «пропускает» этот уровень и смотрит дальше. В твоём случае цепочка выглядит так:
MachinePolicy: Undefined → пропускаемUserPolicy: Undefined → пропускаемProcess: Bypass → стоп, это самое локальное действующее значение. Его и применяем.
Поэтому всё остальное (включая LocalMachine: RemoteSigned) уже не важно: Process перебивает их все.
Что это значит для твоего сценария (C#, BackgroundService, CI/CD)
- Скрипты запускаются без ошибок. Это именно тот результат, который нужен для разовых задач: быстро, безопасно, без изменений в системе.
- Никакой «грязи» не остаётся. Как только терминал закроется,
Processисчезнет, и останется толькоLocalMachine: RemoteSigned— стандартная безопасная настройка. - Идеально для CI/CD. В пайплайнах Azure DevOps/GitHub Actions делают ровно так: на время шага ставят Bypass в Process, прогоняют скрипты, а дальше агент живёт дальше со своими настройками.
Частый вопрос: а если бы Process был Undefined?
Тогда PowerShell взял бы следующее значение по списку. В твоём примере это был бы LocalMachine: RemoteSigned. И тогда .ps1‑скрипты запускались бы только если они подписаны или скачаны из «доверенной» зоны (RemoteSigned).
Но у тебя Process: Bypass, поэтому RemoteSigned даже не участвует в решении.
Практический совет под твой стек
Учитывая, что ты делаешь асинхронный сервис с двухтактной остановкой и часто гоняешь локальные скрипты проверки, держи в голове эту простую формулу:
Если в строке
ProcessвидишьBypass— в этом окне всё будет работать.
Для проверки можешь прямо сейчас сделать:
.\test.ps1
(если файл есть) или:
Get-ExecutionPolicy
И убедиться, что вывод — Bypass. Этого достаточно, чтобы спокойно запускать любые скрипты для тестов, деплоя, проверки логов и т. п.
Если хочешь, могу показать, как оформить такой запуск в виде одной кнопки в VS Code (через tasks.json или через кнопку «Run» для конкретного скрипта), чтобы вообще не думать про политики — они будут применяться автоматически и только на время запуска. 😊
Я
Алиса
Нет, не надо. И стремиться к тому, чтобы везде были прописаны значения вместо Undefined, не нужно — это вообще не признак «правильной» настройки.
Undefined — это не «ошибка» и не «дыра», а нормальное состояние: оно означает «здесь нет своей политики, смотри дальше по цепочке». PowerShell так и задумывался: он идёт сверху вниз и берёт первое найденное значение.
Как на самом деле работает эта цепочка
Представь это как систему исключений:
- MachinePolicy — политика домена (если компьютер в Active Directory). Если тут
Undefined— значит, домен ничего не диктует. - UserPolicy — тоже из групповых политик, но на уровне пользователя. Если
Undefined— пользовательских правил нет. - Process — то, что ты задал прямо сейчас в этом окне. Это самое «сильное» правило для текущего сеанса. У тебя тут
Bypass— и этого достаточно. - CurrentUser — настройка конкретно для этого пользователя (ставится через PowerShell без прав админа).
- LocalMachine — общая настройка для всей машины (нужны права админа). У тебя тут
RemoteSigned— это стандартный безопасный вариант.
Если на каком‑то уровне стоит Undefined, PowerShell просто пропускает этот уровень. В твоём случае он сразу берёт Process: Bypass и дальше не идёт.
Почему не нужно «заполнять» все уровни
- Это не даёт никаких преимуществ. Если ты принудительно задашь, например,
CurrentUser: RemoteSigned, это никак не повлияет на работу скриптов, потому чтоProcess: Bypassвсё равно будет приоритетнее. - Можно случайно сделать хуже. Если поставить политику на уровне
LocalMachineилиCurrentUser, она сохранится после закрытия терминала и будет действовать всегда. Это уже не «временная настройка для теста», а постоянное изменение системы. - Лишние права. Чтобы задать
LocalMachine, нужны права администратора. Для разовых скриптов и CI/CD это избыточно. - Путаница в команде. Если в проекте все начнут ставить свои политики на разных уровнях, у разных разработчиков будут разные правила, и поведение скриптов станет непредсказуемым.
Что это значит для твоего C#‑проекта и скриптов
Твоя текущая картина — идеальна для локальной разработки и CI/CD:
Process Bypass ← работает сейчас, только в этом окне
LocalMachine RemoteSigned ← безопасная база, если Process не задан
Все остальные Undefined ← значит, нет лишних правил
Это как надеть одноразовую перчатку, чтобы быстро что‑то сделать, а потом снять. Ты не меняешь «базовую одежду» системы.
Когда вообще имеет смысл ставить политики на других уровнях
- LocalMachine: RemoteSigned — часто стоит по умолчанию в Windows. Его оставляют как «страховку», если вдруг кто‑то запустит PowerShell без временных настроек.
- CurrentUser — если ты хочешь, чтобы у твоего пользователя по умолчанию были чуть более мягкие правила (но всё равно не Bypass!), и ты готов, что они будут действовать всегда.
- MachinePolicy / UserPolicy — только если ты администратор домена и настраиваешь правила для всей компании.
Для твоих задач (тесты BackgroundService, двухтактная остановка, локальные скрипты, пайплайны) ничего дополнительно настраивать не нужно.
Практический совет под твой стек
Держи в голове простое правило:
Для тестов, деплоя и CI/CD достаточно, чтобы в строке
ProcessбылоBypass. Всё остальное может спокойно оставатьсяUndefined.
Если хочешь, могу показать, как оформить запуск твоего скрипта проверки остановки сервиса так, чтобы Set-ExecutionPolicy вообще не приходилось вводить вручную — через задачу VS Code или через параметры запуска pwsh, чтобы это было удобно и безопасно. Что ближе? 😊