【问题标题】:Restart environment and script during batch script批处理脚本期间重启环境和脚本
【发布时间】:2020-07-13 15:47:17
【问题描述】:

我已经为我和其他一些人构建了一些 FFmpeg powershell 脚本以供使用,并且我正在尝试使设置和更新过程尽可能简单。最终目标是能够运行 1 个安装 Chocolatey、FFmpeg、git、克隆 github 存储库(用于更新)并编辑 Windows 注册表以将实际 FFmpeg powershell 脚本/控制台程序添加到 Windows 资源管理器上下文菜单的批处理文件.这样,我只需将包含所有内容的文件夹传递给他们一次,每当我更改或向项目添加某些内容时,我可以告诉他们再次运行批处理文件,并且所有内容都是最新的。

但是,我正在努力寻找一种方法来安装 Chocolatey,然后使用 Chocolatey 进行 git,然后在执行单个 .bat 文件的情况下运行 git 命令。从我在安装 Chocolatey 后的情况来看,我需要完全重新启动 shell,然后才能安装 git,然后我必须再次重新启动 shell,然后才能使用 git 命令。截至目前,大多数实际处理都是通过从 .bat 文件启动的 Powershell 脚本进行的,并且随着每一步的执行,我都会更新一个 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 安装的同一个进程中产生的,它不算实际重新启动贝壳。有什么方法可以真正重新启动 shell 并以某种方式在无需用户干预的情况下启动批处理文件?

【问题讨论】:

  • 补充几点:比较数字时最好使用EQU 而不是==(参见help if)。变量relativePath 命名错误,因为%~dp0 返回一个绝对 路径。

标签: powershell batch-file github ffmpeg chocolatey


【解决方案1】:

我不确定为什么我最初没有考虑重新加载路径环境变量,但这比使用中间文件重新启动脚本 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 表示 [System.Environment]::GetEnvironmentVariable 方法,但请注意,您仍然可以使用 Chocolatey,它具有重新加载 all 环境变量的优势(尽管这可能不会在您的情况下是必要的)。 从 PowerShell 调用 RefreshEnv.cmd 无法正常工作,因为它随后会运行进程外。但是,Chocolatey 还附带了一个等效的 PowerShell 命令 - 请参阅我的更新。
【解决方案2】:

确实,start-launched 进程继承了调用进程的环境,而不是从注册表中读取可能更新的环境变量定义。

Chocolatey 附带批处理文件 RefreshEnv.cmdC:\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 仅在脚本执行期间安装,因此其二进制文件夹尚未在 %Path% 中,因此您必须通过其完整路径调用 RefreshEnv.cmd,如上所示- 假定默认安装目录。


Your own answer 现在展示了如何使用 .NET 方法直接从 PowerShell 刷新$env:Path (%Path%) 环境变量,这是一个实用的解决方案。

但是请注意,RefreshEnv.cmd 更全面,因为它会重新加载所有环境变量定义,因此可能会重新加载和修改新的定义


请注意,从 PowerShell 调用 RefreshEnv.cmd 确实 工作,因为它随后运行 进程外(这意味着它无法更新调用进程的环境)。

但是,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

请参阅this answer 了解更强大的方法,该方法不依赖于假设已安装到默认位置。


【讨论】:

    猜你喜欢
    • 2012-03-19
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多