Вопрос или проблема
Почему так сложно сделать профиль PowerShell, который выполняет определенные действия только в интерактивном хосте.
В Linux оболочках довольно легко различить профили и скрипты rc, чтобы вещи, которые вы хотите, чтобы существовали только в интерактивной сессии, загружались только тогда. Мне не удалось сделать то же самое с PowerShell (5.1 на Windows 11). Даже Google и ChatGPT предлагают только решения, которые не работают. Я не могу использовать $Args, $Host.Name, Host.UI.RawUI.KeyAvailable или $MyInvocation, потому что простое условие “когда используется powershell.exe -command
или powershell.exe -file
или “Запустить в PowerShell” в проводнике, тогда определенный блок кода в моем скрипте профиля должен быть пропущен.
Я знаю, что могу использовать -NoProfile
, и это довольно важно всегда его использовать. Тем не менее, я хочу, чтобы мой profile.ps1 был хорошим гражданином и не требовал этого. Не говоря уже о том, что я хочу понять, почему это так сложно и почему это нигде не упоминается как лучшая практика, и почему вы находите только ответы, которые не работают.
Например, $Host.Name
– это 'ConsoleHost'
, когда я запускаю powershell.exe из другого powershell.exe, что, конечно, нормально, если вы пытаетесь использовать только окна PowerShell.
В моем случае мне все равно, если это сеанс в Windows Terminal, терминале VS Code или старом стиле хоста powershell.exe (поскольку он запущен с “Запуск от имени администратора”), в только этих случаях я хочу, чтобы мой профиль выполнял код.
Я мог бы, вероятно, использовать $PID и проверить процесс, но это выглядит ужасно сложно для как будто бы обычной задачи?
Вы можете использовать [Environment]::GetCommandLineArgs()
, чтобы проверить параметры неинтерактивного типа, такие как -command
или -file
Ответ или решение
Создание профиля PowerShell, который выполняет определенные действия только в интерактивных сеансах, действительно может быть сложной задачей. В отличие от Linux, где обычно можно легко разделить конфигурацию для интерактивных и неинтерактивных оболочек, в PowerShell этого сделать гораздо сложнее из-за различных сценариев запуска и хостов.
Тем не менее, есть несколько подходов, которые могут помочь решить вашу проблему. Ниже представлен один из наиболее практичных способов, используя метод [Environment]::GetCommandLineArgs()
, который позволяет проверить параметры командной строки, переданные запущенному процессу PowerShell.
Пример решения
# Получение аргументов командной строки
$commandLineArgs = [Environment]::GetCommandLineArgs()
# Проверка на наличие определенных аргументов, определяющих неинтерактивный запуск
if ($commandLineArgs -notcontains '-command' -and $commandLineArgs -notcontains '-file') {
# Ваш код для интерактивного сеанса
Write-Host "Это интерактивный сеанс PowerShell."
# Добавьте здесь код, который вы хотите выполнять в интерактивных сеансах
} else {
Write-Host "Это не интерактивный сеанс PowerShell. Профиль не будет выполнен."
}
Объяснение
-
Получение аргументов командной строки: Этот код использует метод
GetCommandLineArgs()
для получения аргументов, переданных процессу при запуске. Это поможет определить, запущен ли PowerShell с параметрами-command
или-file
. -
Условная проверка: Условие проверяет, не содержат ли аргументы командной строки указанные параметры. Если они отсутствуют, значит, сеанс является интерактивным, и можно выполнять соответствующий код.
-
Вывод сообщений: Код выводит сообщения, чтобы вы могли видеть, какую часть выполняет на текущий момент. Вы можете заменить эти сообщения вашим функционалом.
Заключение
Хотя подход к разделению настройки профиля PowerShell для интерактивных и неинтерактивных сеансов отличается от аналогичного подхода в Linux, использование GetCommandLineArgs()
может значительно упростить вашу задачу. Это позволяет сделать ваш профиль более гибким и адаптивным к различным сценариям запуска.
Обратите внимание, что важно тестировать данный код в различных сценариях использования PowerShell, чтобы убедиться, что он работает так, как вам нужно.