«Запуск с PowerShell» выдает ошибку политики выполнения, но запуск непосредственно в окне PowerShell не дает

У меня есть простой скрипт .ps1, который просто создает каталог. Когда я щелкаю правой кнопкой мыши сценарий в проводнике Windows и выбираю «Запустить с помощью PowerShell», появляется следующее сообщение об ошибке:

Get-ExecutionPolicy: Windows PowerShell успешно обновила вашу политику выполнения, но этот параметр переопределяется политикой, определенной в более конкретной области. Из-за переопределения ваша оболочка сохранит текущую эффективную политику выполнения Unrestricted. Введите «Get-ExecutionPolicy -List», чтобы просмотреть параметры политики выполнения. Для получения дополнительной информации см. «Get-Help Set-ExecutionPolicy».

(Я записал свой экран и напечатал все вышеперечисленное, так как окно быстро мигало. Кроме того, если я запускаю «powershell -NoExit C:\path\to\script.ps1», ошибки не будет.

Интересно, что папка все еще создается.

Однако если я сам открою PowerShell и запущу скрипт, например .\script.ps1, ошибок не будет.

Вот результат Get-ExecutionPolicy -List:

        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy    Unrestricted
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine    Unrestricted

Я думаю, что «Запуск с PowerShell» пытается что-то сделать (например, установить политику выполнения) перед запуском сценария, но я не вижу полной команды, которую он вызвал, и не знаю, для какой области он пытается установить политику выполнения. . Кроме того, что из вышеперечисленного является более конкретным, чем что из остальных?

У меня также нет прав администратора, чтобы переопределить этот пункт контекстного меню. Как мне добиться чистого исполнения?

Может отличаться от Невозможно выполнить сценарий PowerShell с использованием опции «Запустить с Powershell», поскольку кажется, что мое выполнение действительно удалось.

Я ожидаю, что сценарий будет запущен без проблем из проводника Windows, т. е. не должно быть никаких ошибок.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
97
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В Windows 10 команда контекстного меню Windows PowerShell Run with PowerShell (определенная в реестре) пытается переопределить политику выполнения для конкретного процесса через CLI, вызывая Set-ExecutionPolicy -Scope Process Bypass как часть кода, переданного в параметр -Command.

Однако, поскольку политика выполнения вашего компьютера управляется объектом групповой политики (GPO), на что указывает выходная строка MachinePolicy, имеющая значение, отличное от Undefined, ни переопределения через параметр -ExecutionPolicy CLI, ни через Set-ExecutionPolicy не эффективны.

Это то, что пытается сказать вам сообщение об ошибке; в частности, это означает: я применил запрошенное вами изменение, но оно не имеет никакого эффекта.

  • В качестве отступления: к сожалению, то, что должно было быть предупреждением, отображается как ошибка, но было решено не менять это в интересах обратной совместимости; см. выпуск GitHub № 12032

Сама ошибка не останавливает выполнение, которое продолжается при действующей политике, контролируемой объектом групповой политики.

Учитывая, что в вашем случае действующей политикой объекта групповой политики является Unrestricted (что, вероятно, должно быть RemoteSigned для большей безопасности), ваши сценарии все равно будут выполняться, и вы можете игнорировать сообщение об ошибке.

Чтобы сообщение об ошибке исчезло, можно удалить вызов Set-ExecutionPolicy из определения команды в реестре.
Его модификация требует повышения прав, то есть административных привилегий, поскольку он находится в кусте реестра HKEY_LOCAL_MACHINE; однако в кусте HKEY_CURRENT_USER можно определить эквиваленты для конкретного пользователя, которые, следовательно, не требуют повышения прав — см. ниже.

Другой вариант — деактивировать соответствующий объект групповой политики, который, учитывая, что это MachinePolicy, по крайней мере, также требует повышения прав, но обычно не находится под вашим контролем в среде домена.


Изменение/переопределение команды для пропуска вызова Set-Execution и, следовательно, подавления предупреждения:

В Windows 10 должно работать следующее (я больше не могу лично проверить), основываясь на информации в нижней части этого ответа, адаптированной для любого типа файла, зарегистрированного в данный момент для .ps1 файлов, который может отличаться от по умолчанию, особенно если у вас установлен код Visual Studio:

# Determine the registry key path, based on the HKEY_CURRENT_USER
# equivalent of the file-type key.
$regKey = 'registry::HKEY_CURRENT_USER\Software\Classes\{0}\shell\Run with PowerShell\Command' -f (Get-ItemPropertyValue registry::HKEY_CLASSES_ROOT\.ps1 '(Default)')

# Create the key, if necessary.
if (-not (Test-Path $regKey)) { $null = New-Item -Force -ErrorAction Stop $regKey }

# Define the command line, without Set-ExecutionPolicy and with -NoExit.
Set-ItemProperty $regKey '(Default)' '"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoExit -File "%1"'

Это создает HKEY_CURRENT_USER эквивалент (потенциально) HKEY_LOCAL_MACHINE определения команды контекстного меню, которое должно переопределять последнее, учитывая, что куст HKEY_CLASSES_ROOT, через который загружаются определения контекстного меню, представляет собой составное представление первых двух ульев. ' Software\Classes пути, причем определения на уровне пользователя имеют приоритет.

Также обратите внимание, что -NoExit был добавлен, чтобы сохранить сеанс после выполнения скрипта и, следовательно, открыть окно.

Если у вас есть права администратора, вы можете заменить HKEY_CURRENT_USER на HKEY_LOCAL_MACHINE в приведенном выше коде и запустить его с повышенными правами.


В Windows 11 проблема больше не возникает, поскольку настроенный там вызов CLI Windows PowerShell больше не пытается изменить политику выполнения.

Однако вы все равно можете изменить вызов, а именно включить переключатель -NoExit (чтобы сеанс оставался активным и окно оставалось открытым после выполнения скрипта): см. этот ответ.


В PowerShell (Core) 7, который больше не поддерживается в Windows 10, проблема также не возникает: не предпринимается никаких попыток установить политику выполнения.

  • По сути, команды контекстного меню доступны только в том случае, если вы устанавливаете PowerShell 7 через пакет MSI, где вы получаете возможность устанавливать команды для папок и дисков, а также для запуска отдельных *.ps1 файлов (как в Windows PowerShell). .

  • Чтобы их увидеть, необходимо удерживать Shift и щелкнуть правой кнопкой мыши.

  • Команды уровня папки/диска (подменю PowerShell 7) открывают интерактивный сеанс в целевой папке или диске.

  • Команда уровня файла *.ps1, хранящаяся в HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\PowerShell7x64\Command, начиная с PowerShell 7.4.3:

    • кажется сломанным: по крайней мере, на моей машине это никогда не отображается.

    • неверно определено:

      • C:\Program Files\PowerShell\7\pwsh.exe -Command "$host.UI.RawUI.WindowTitle = 'PowerShell 7 (x64)'; & '%1'"
      • Фундаментально концептуальная проблема заключается в том, что в пути к исполняемому файлу отсутствует вложение "...", которое требуется для пути, содержащего пробелы - как ни странно, это само по себе не является проблемой (это также влияет на команды уровня папки/диска, которые действительно работают).
      • Вторичная проблема заключается в том, что заключение пути в '...' не является надежным, учитывая, что ' является допустимым символом в путях.
    • Даже если это сработало так, как задумано, вы также можете изменить его, включив -NoExit, чтобы предотвратить автоматическое закрытие окна после выполнения скрипта.

О... Теперь это имеет смысл... Могу ли я создать локальную для пользователя версию «Запуск с PowerShell», которая запускает сценарий без установки политики выполнения на уровне процесса?

charlesz 27.06.2024 23:15

@charlesz, да, как (сейчас) отмечено в ответе, вы можете создать эквивалентные определения в кусте реестра HKEY_CURRENT_USER.

mklement0 27.06.2024 23:17

«но было решено не менять это в интересах обратной совместимости» — постоянное препятствие на пути прогресса PowerShell..

Maximilian Burszley 27.06.2024 23:19

@mklement0 Да. Я использую Windows 10. Позвольте мне попробовать в следующий раз, когда я буду над этим работать.

charlesz 28.06.2024 21:46

@mklement0 Я предполагаю, что вы имеете в виду HKCU\Software\Classes\Microsoft.PowerShellScript.1 (потому что подобная вещь есть в HKLM? -- Этот ключ не существует. Я, вероятно, могу создать его, но как мне просто добавить пункт контекстного меню, но не устанавливать его в качестве метода открытия по умолчанию? С этого момента «Запуск с PowerShell» не используется по умолчанию. Если я дважды щелкну файл PS1, откроется VS Code.

charlesz 28.06.2024 22:30

@charlesz, да, извини; это часть \0\, которая относится к команде «Выполнить с помощью PowerShell», если мне не изменяет память, и я думаю, что запись в аналогичное место в кусте HKCU должна переопределить настройку HKLM. Пожалуйста, посмотрите новый нижний раздел, который я добавил к ответу.

mklement0 28.06.2024 22:47

Заставил это работать сейчас. Спасибо! @mklement0 Единственное предостережение: я использую VS Code, поэтому он должен находиться в разделе «VSCode.ps1» вместо «Microsoft.PowerShellScript.1». «0» может быть чем угодно, и пока для него установлено значение по умолчанию, оно использует это значение в качестве текста контекстного меню.

charlesz 29.06.2024 08:54

Кажется, не было способа добавить это независимо от класса, определяющего открытый метод. Могу поспорить, что это должен быть либо «Microsoft.PowerShellScript.1», либо «VSCode.ps1», либо что-то еще, что вы используете для его открытия. Я пробовал добавлять прямо в .ps1 в классах, но не получилось.

charlesz 01.07.2024 21:16

@charlesz, вы можете попытаться выбрать любой тип файла, определенный для файлов .ps1 (хотя, если вы измените тип файла позже, вам, возможно, придется повторить его); пожалуйста, посмотрите мое обновление.

mklement0 01.07.2024 22:29

Другие вопросы по теме