Как передать данные из сценария PowerShell в команду Windows

Мне нужно изменить запуск командного файла для сайта, написанного на Micro Focus COBOL, чтобы получить доступ к хранилищу ключей Azure. Я написал сценарий PowerShell для доступа к хранилищу ключей. Мне нужно вернуться к данным командного файла, которые командный файл использует для установки переменных среды. Я не хочу передавать переменную на уровне компьютера — это лишит смысла использование хранилища ключей. Как отправить строковую переменную обратно в командный файл?

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

командный файл запуска

ECHO SETTING ENVIRONMENT SPECIFIC VARIABLES
SET REGION_NAME=theRegion

powershell.exe -File "C:\Util\CallAzure.Ps1"

SET FIRST_ENV_VAR=DSN=DataSet;UID=UserID;PWD=%FromPowerShell%
...
SET SHAREDFILE_LOCATION=\\theServer\theFolder
ECHO DONE SETTING ENVIRONMENT SPECIFIC VARIABLES

сценарий PowerShell

ECHO 'SETTING ENVIRONMENT SPECIFIC VARIABLES - PowerShell'

$Url = "https://lookupdv.site.org/API.KeyVault"
$JSON = "application/json"
$Body = @{
    URI = "KeyName"
    secretname = "UserID"
}
$Password = Invoke-RestMethod -Method 'Post' -Uri $url -ContentType $JSON -Body ($body | ConvertTo-Json)

[System.Environment]::SetEnvironmentVariable('FromPowerShell', $Password, [System.EnvironmentVariableTarget]::Process)

ECHO 'DONE SETTING ENVIRONMENT SPECIFIC VARIABLES - PowerShell'

это не работает

следует ли мне изменить команду Set на пользователя вместо процесса?

Среда, созданная в начале powershell.exe -File "...", теряется, когда выполнение сценария PowerShell завершается.

Luuk 20.05.2024 13:59
Стоит ли изучать 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
2
98
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

«for» Cmd может установить переменную в качестве вывода команды. Удвойте % в файле .bat.

echo echo hi > script.ps1
for /f %i in ('powershell -file script.ps1') do set a=%i
echo %a%

hi
Ответ принят как подходящий
  • Как отмечает Люук, дочерний процесс не может изменять среду своего родительского процесса, поэтому любые изменения среды на уровне процесса, сделанные дочерним процессом powershell.exe, неизменно теряются, когда управление возвращается вызывающему объекту (вашему пакетному файлу).

  • Однако, если вы знаете, какую переменную среды уровня процесса устанавливает ваш сценарий PowerShell, вы можете вызвать powershell.exe, CLI Windows PowerShell, таким образом, чтобы отображать (выводить) эту переменную (значение) через ее поток stdout, позволяющий вашему пакетному файлу захватить его с помощью оператора for /f; для этого вы должны использовать параметр -Command, а не параметр -File; -Command позволяет передать фрагмент кода PowerShell.

Вот фрагмент пакетного файла, иллюстрирующий этот подход.
Обратите внимание, что для этого не требуется никаких изменений в вашем скрипте C:\Util\CallAzure.Ps1, поскольку именно фрагмент кода PowerShell, переданный в -Command, гарантирует вывод интересующего значения переменной среды:

:: ...

:: Define the PowerShell command line that calls the PowerShell script
:: and then echoes the "FromPowerShell" environment variable that was set
:: in the script.
set pscmd=powershell.exe -Command "C:\Util\CallAzure.Ps1 >$null; $env:FromPowerShell"

:: Invoke the PowerShell command line, and save its only output line in a
:: variable (for the current process.)
for /f "usebackq delims = " %%i in (`%pscmd%`) do set "FromPowerShell=%%i"

:: %FromPowerShell% now contains the value of interest.

:: ...

Примечание:

  • >$null выше подавляет вывод успеха сценария .ps1 (stdout) (сообщения о состоянии), так что вызов -Command выводит только значение переменной среды и ничего больше.

  • Если вы все еще хотите видеть этот вывод, вам придется перенаправить его на stderr, определив командную строку PowerShell следующим образом:

    set pscmd=powershell.exe -NoProfile -Command "[Console]::Error.WriteLine((C:\Util\CallAzure.Ps1) -join [char] 10); $env:FromPowerShell"
    

Примечание:

  • Из вышесказанного следует, что альтернативой является изменение вашего .ps1 файла следующим образом:

    • Заставьте его выводить значение переменной среды.

    • Убедитесь, что сообщения о состоянии, напечатанные сценарием, используют [Console]::Error.WriteLine(), а не echo (также известный как Write-Output), т. е. что сообщения о состоянии не «загрязняют» поток вывода успеха и, следовательно, стандартный вывод.

    • При таком подходе даже нет строгой необходимости устанавливать значение переменной среды в сценарии PowerShell: просто выведите интересующее значение напрямую.

  • Затем вы можете вызвать свой .ps1 файл с помощью -File вызова CLI PowerShell, как и раньше.


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

  • Чтобы поддерживать несколько из них, вы можете создать пары «имя-значение» вашего сценария .ps1, которые можно будет передать set в вызывающем пакетном файле, например, вывести 'FOO=BAR' и 'BAZ=QUX' из вашего сценария PowerShell, и изменить команду set в цикле for /f в пакете. файл в set "%%i", как показано ниже.

Пример с несколькими значениями:

  • Пример C:\Util\CallAzure.Ps1 контента:

    # Print status messages to stderr, to avoid polluting
    # stdout.
    [Console]::Error.WriteLine('Outputting name-value pairs.')
    
    # Output name-value pairs, to be set as environment variables
    # by the batch file.
    'FOO=BAR'
    'BAZ=QUX'
    
  • Пример содержимого пакетного файла:

     @echo off & setlocal
     :: Remove `& setlocal` if you want to variables set by this
     :: batch file to persist in a `cmd.exe` session.
    
     :: Define the PowerShell command line that calls the .ps1 script
     set pscmd=powershell.exe -noprofile -File C:\Util\CallAzure.Ps1
    
     :: Invoke the PowerShell command line, and pass the name-value
     :: pairs to `set`, which defines them as process-level 
     :: environment variables.
     for /f "usebackq delims = " %%i in (`%pscmd%`) do set "%%i"
    
     :: Echo the resulting variables for diagnostic purposes.
     echo [%FOO%]
     echo [%BAZ%]
    

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