Доступ к обновленному пути из скрипта Powershell

546
Eos Pengwern

Я пишу сценарий Powershell, чтобы настроить среду сборки и затем выполнить сборку. Это влечет за собой установку системного пути так, чтобы он включал компилятор и систему сборки (в данном случае qmake и mingw32-make), а затем продолжил сборку.

Я настроил все так, чтобы функция для изменения системного пути, в широком смысле основанная на этой ссылке, находилась в отдельном файле, подобном следующему:

Function AddTo-UserPath { Param ( [Parameter(mandatory=$true)] [System.IO.DirectoryInfo[]]$PathsToAdd )  $MachinePath = [System.Environment]::GetEnvironmentVariable('PATH','Machine') $UserPath = [System.Environment]::GetEnvironmentVariable('PATH','User') $VerifiedPathsToAdd = $Null $MachinePathArray = $MachinePath -Split ‘;’ -replace ‘\\+$' $UserPathArray = $UserPath -Split ‘;’ -replace ‘\\+$' Foreach ($PathToAdd in ($PathsToAdd | % { $_.FullName.TrimEnd(‘\’) } ) ) { if($MachinePathArray -contains $PathToAdd) { Write-Verbose “$PathToAdd already exists in Machine Path” } elseif($UserPathArray -contains $PathToAdd) { Write-Verbose “$PathToAdd already exists in User Path” } else { $VerifiedPathsToAdd += ";$PathToAdd" } }  if($VerifiedPathsToAdd -ne $null) { [Environment]::SetEnvironmentVariable('PATH', $UserPath + $VerifiedPathsToAdd, 'User') } } 

... так что в моем основном файле сценария я могу написать:

# Load the module containing the AddTo-UserPath function Import-Module $PSScriptRoot\..\ps1utils\myfunctions.ps1  # Add the required directories to the system path AddTo-UserPath C:\Qt\Tools\mingw530_32\bin, C:\Qt\5.9.7\mingw53_32\bin  # Start the build qmake qwt.pro mingw32-make -j mingw32-make -j install 

Если я запускаю свой сценарий из PowerShell ISE, я могу поставить точку останова в строке 'qmake' и проверить из графического интерфейса Windows, что мой путь был изменен, как требуется; Я даже могу открыть отдельное окно cmd и довольно успешно запустить qmake и mingw32-make. Мой сценарий, однако, дает мне ошибки:

qmake : The term 'qmake' is not recognized as the name of a cmdlet, function, script file, or operable program. mingw32-make : The term 'mingw32-make' is not recognized as the name of a cmdlet, function, script file, or operable program.  

... и если я проверю значение $ env: Path, то оно точно не отразит изменения, которые я только что сделал.

В некотором смысле это не удивительно; Я много раз читал, что если вы измените системный путь из окна Powershell, вам придется закрыть и снова открыть окно, чтобы изменения вступили в силу. Проблема в том, что я не могу понять, как обойти это из моего скрипта - весь смысл в этом заключается в том, чтобы автоматизировать процесс сборки, поэтому вряд ли мне уместно вручную закрывать одно окно Powershell и открывать еще один, прежде чем мой сценарий может продолжить. Там должен быть лучший путь.

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

AddTo-UserPath C:\Qt\Tools\mingw530_32\bin, C:\Qt\5.9.7\mingw53_32\bin powershell -file TheRestOfMyBuildProcess.ps1 

... но это тоже не сработало.

Так что теперь у меня нет идей, я не смог найти решение в Интернете, и я хотел бы знать, как правильно это сделать.

1

1 ответ на вопрос

1
harrymc

Изменение PATH в PowerShell изолировано от текущего сеанса и является только временным, что вы и видите.

Вы можете внести постоянные изменения в переменную среды PATH, изменив ее непосредственно в реестре. Все переменные хранятся в разделе реестра HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment.

Сценарий PowerShell для добавления в PATH будет выглядеть следующим образом:

$oldPath=(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path  $newPath=$oldPath+’;C:NewFolderToAddToTheList’  Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' -Name PATH –Value $newPath 

Вам нужно будет перезапустить PowerShell, чтобы увидеть изменения, но теперь все приложения будут использовать обновленный PATH.

Это было найдено в статье «Привет, автор сценариев! Блог». Используйте PowerShell для изменения своего экологического пути, где вы найдете больше информации и идей.

Еще один полезный пост - это Перезагрузить путь в powershell, где был предложен следующий синтаксис:

$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") 
Спасибо за ваш ответ, но, боюсь, это мне не поможет. То, что я вижу, не имеет ничего общего с временным изменением пути. Поскольку я делаю это с помощью команды .Net SetEnvironmentVariable, она фактически является постоянной; Я проверил это тщательно. Проблема в том, что Powershell не видит обновленный путь. Мне нужен способ заставить Powershell увидеть его, даже если это означает программный перезапуск Powershell и продолжение моего сценария. Поскольку предполагается, что Powershell полностью посвящен автоматизации, трудно поверить, что нет способа автоматизировать такую ​​сборку, Eos Pengwern 6 лет назад 0
Вам необходимо перезапустить Powershell, чтобы воссоздать PATH, но не как дочерний элемент текущего сценария, так как дочерний объект наследует родительскую среду. Я добавил возможное решение для перезагрузки PATH в текущем сеансе после постоянного изменения. harrymc 6 лет назад 0
Это выглядит намного более многообещающе, но я боюсь, что не смогу попробовать это в течение 24 часов или около того; Я дам вам знать, если это удастся, и приму ваш ответ, если так. Eos Pengwern 6 лет назад 0
Не спешите и удачи. harrymc 6 лет назад 0
Да, это прибито это. Я приму ваш ответ сейчас. Eos Pengwern 6 лет назад 0