Перезапустите среду и скрипт во время пакетного скрипта - PullRequest
1 голос
/ 01 апреля 2020

Я создал несколько сценариев FFmpeg для PowerShell для себя и нескольких других пользователей, и я пытаюсь максимально упростить процесс установки и обновления. Конечная цель заключается в том, чтобы иметь возможность запустить 1 пакетный файл, который устанавливает Chocolatey, FFmpeg, git, клонирует репозиторий github (для обновлений) и редактирует реестр Windows, чтобы добавить фактические сценарии / консольные программы PowerShell FFmpeg в консоль. Windows Проводник контекстного меню. Таким образом, я просто передаю им папку, содержащую все, один раз и каждый раз, когда я изменяю или добавляю что-то в проект, я могу просто сказать им, чтобы они снова запустили пакетный файл, и до того, как все обновится.

Однако я Я пытаюсь найти способ установить Chocolatey, затем git с Chocolatey, а затем запустить команду git с выполнением одного файла .bat. Из того, что я могу сказать после установки Chocolatey, мне нужно полностью перезапустить оболочку, прежде чем я смогу установить git, а затем мне нужно перезапустить оболочку еще раз, прежде чем я смогу использовать команду git. На данный момент большая часть фактической обработки происходит через скрипты Powershell, которые запускаются из файла .bat, и по мере выполнения каждого шага я обновляю txt-файл, пытаюсь перезапустить пакетный скрипт и читаю txt-файл, чтобы получить его. где я остановился:

@echo off
echo Administrative permissions required. Detecting permissions...
echo.

net session >nul 2>&1
if %errorLevel% == 0 (
    echo Success: Administrative permissions confirmed.
    echo.
) else (
    echo Failure: Current permissions inadequate.

    PAUSE

    exit
)

set relativePath=%~dp0
set relativePath=%relativePath:~0,-1%

PowerShell -NoProfile -ExecutionPolicy Bypass -File "%relativePath%\Setup\CheckRequiredPackages.ps1" -relativePath "%relativePath%"

set /p step=<"%relativePath%\Setup\Step.txt"

if %step% == 1 (
    (echo 2) > "%relativePath%\Setup\Step.txt"

    PowerShell -NoProfile -ExecutionPolicy Bypass -File "%relativePath%\Setup\GetChocolatey.ps1"

    start "" "%relativePath%\RunMe.bat"

    exit
) 

if %step% == 2 (
    (echo 3) > "%relativePath%\Setup\Step.txt"

    PowerShell -NoProfile -ExecutionPolicy Bypass -File "%relativePath%\Setup\GetRequiredPackages.ps1"

    start "" "%relativePath%\RunMe.bat"

    exit
) 

if %step% == 3 (
    (echo 0) > "%relativePath%\Setup\Step.txt"

    PowerShell -NoProfile -ExecutionPolicy Bypass -File "%relativePath%\Setup\Update.ps1" -relativePath "%relativePath%"
) 

PAUSE
Exit

Проблема в использовании команды start в пакетном скрипте, похоже, не работает, я полагаю, так как этот новый процесс создается из того же процесса, который обрабатывает установка Chocolatey не считается перезапуском оболочки. Есть ли способ перезапустить оболочку и каким-то образом запустить пакетный файл без вмешательства пользователя?

Ответы [ 2 ]

1 голос
/ 03 апреля 2020

Я не уверен, почему я изначально не думал о перезагрузке переменной окружения path, но это гораздо разумнее, чем перезапуск сценария 4 раза с промежуточным файлом.

Сначала я переместился на 99% тяжелой работы из файла .bat в сценарий Powershell, поскольку единственная причина, по которой я использую Batch, заключается в том, что пользователь может легко запустить файл, щелкнув его в проводнике. Я не мог заставить RefreshEnv работать, что является особенностью Chocolatey, но запуск этого между каждым новым пакетом работал замечательно:

$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")

Так что у меня сейчас что-то вроде этого, и пакетный скрипт просто запускает этот скрипт Powershell:

Write-Host "Installing / updating required packages..."

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = 
[System.Net.ServicePointManager]::SecurityProtocol -bor 3072; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")

choco install ffmpeg -y
choco install git -y

$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") 

Write-Host "Deleting old files..."

Remove-Item -LiteralPath $relativePath -Force -Recurse
Start-Sleep 2

Write-Host "`nUpdating Files..."
git clone https://github.com/TheNimble1/FFmpegContextCommands.git $relativePath

, который устанавливает Chocolatey, обновляет путь, устанавливает FFmpeg & Git, обновляет путь, удаляет старые файлы, а затем клонирует git для замены новыми файлами .

1 голос
/ 01 апреля 2020

Действительно, start -запущенный процесс наследует среду вызывающего процесса ', а не считывает возможно обновленные определения переменных среды из реестра.

Chocolatey поставляется с пакетом файл RefreshEnv.cmd (C:\ProgramData\chocolatey\bin\RefreshEnv.cmd, но C:\ProgramData\chocolatey\bin должен быть в %PATH%) специально, чтобы избежать необходимости начинать новый независимый сеанс, чтобы обновления среды вступили в силу .

Следовательно, может работать что-то вроде следующего:

:: Assumes that Chocolatey was just installed to the default location.
call "%ProgramData%\chocolatey\bin\RefreshEnv.cmd"

:: If Chocolatey was *previously* installed and its installation directory
:: has already been added to %Path%, the following will do:
::   call RefreshEnv.cmd

call "%relativePath%\RunMe.bat" 

Поскольку Chocolatey устанавливается только во время выполнения вашего скрипта, и поэтому его папка binaries еще не находится в %Path%, вам придется вызывать RefreshEnv.cmd по его полный путь , как показано выше - который предполагает каталог установки по умолчанию.


Ваш собственный ответ теперь показывает, как обновить sh $env:Path (%Path%) переменная окружения с использованием. NET методов непосредственно из PowerShell, что является прагматическим c решением.

Обратите внимание, однако, что RefreshEnv.cmd является более полным в этой области. t он перезагружает все определения переменных среды и, следовательно, потенциально новые и измененные .


Обратите внимание, что вызов RefreshEnv.cmd из PowerShell не работает, потому что затем он запускает вне процесса (что означает, что он не может обновить вызывающую среду процесса ').

Однако, Chocolatey предлагает команду Update-SessionEnvironment PowerShell (с псевдонимом refreshenv) , которую можно сделать доступной сразу после установки Chocolatey следующим образом:

# Import the module that defines Update-SessionEnvironment aka refreshenv
Import-Module "$env:ProgramData\Chocolatey\helpers\chocolateyProfile.psm1"

# Refresh all environment variables.
Update-SessionEnvironment  # or: refreshenv

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


...