Как перезагрузить профиль пользователя из script файла в PowerShell
Я хочу перезагрузить мой профиль пользователя из файла script. Я думал, что точка, найденная из файла script, сделает трюк, но не работает:
# file.ps1
. $PROFILE
Однако, он работает, если я получаю его источник от интерпретатора PowerShell.
Почему я хочу это сделать?
Я запускаю этот script каждый раз, когда я обновляю свой профиль и хочу его протестировать, поэтому я бы не хотел перезапускать PowerShell для обновления среды.
Ответы
Ответ 1
Итак, подход, который вы отметили в качестве ответа, может работать внутри командной строки Powershell, но он не работает внутри PowerShell ISE (который, для меня, обеспечивает превосходный сеанс PowerShell) и, вероятно, не будет работать правильно в других средах PowerShell.
Здесь script, который я использовал некоторое время, и он работал очень хорошо для меня в каждой среде. Я просто поместил эту функцию в свой Profile.ps1 в ~\Documents\WindowsPowerShell, и всякий раз, когда я хочу перезагрузить мой профиль, я передам функцию-точка, т.е.
. Reload-Profile
Здесь функция:
function Reload-Profile {
@(
$Profile.AllUsersAllHosts,
$Profile.AllUsersCurrentHost,
$Profile.CurrentUserAllHosts,
$Profile.CurrentUserCurrentHost
) | % {
if(Test-Path $_){
Write-Verbose "Running $_"
. $_
}
}
}
Ответ 2
Если вы хотите глобально обновить свой профиль из script, вам нужно будет запустить этот script "dot-sourced".
При запуске script весь профиль script работает в области "script" и не будет изменять вашу "глобальную" область.
Чтобы script изменил вашу глобальную область действия, он должен быть "точечным источником" или ему предшествует период.
. ./yourrestartscript.ps1
где у вас есть профиль script "dot-sourced" внутри "yourrestartscript.ps1". То, что вы на самом деле делаете, говорит "yourrestartscript" для запуска в текущей области и внутри script, вы сообщаете $profile script для запуска в области script. Поскольку область script является глобальной областью, любые переменные или команды в вашем профиле будут выполняться в глобальной области.
Это не дает вам много преимуществ перед запуском
. $profile
Ответ 3
Почему вы пытаетесь это сделать?
Поскольку он может создавать дубликаты (добавляет к $env: path) и проблемы с установкой констант /readonly объектов, вызывающих ошибки.
Недавно была тема на эту тему microsoft.public.windows.powershell.
Если вы пытаетесь выполнить reset состояние сеанса, нет способа сделать это, даже используя внутреннюю область ($host.EnterNestedPrompt()
) из-за возможности устанавливать переменные/псевдонимы/... на "все сфера".
Ответ 4
& $profile
работает, чтобы перезагрузить профиль.
Если ваш профиль задает псевдонимы или выполняет импорт, которые терпят неудачу, вы увидите ошибки, поскольку они уже были установлены при предыдущей загрузке профиля.
Ответ 5
Я нашел это обходное решение:
#some-script.ps1
#restart profile (open new powershell session)
cmd.exe /c start powershell.exe -c { Set-Location $PWD } -NoExit
Stop-Process -Id $PID
Более подробная версия:
#publish.ps1
# Copy profile files to PowerShell user profile folder and restart PowerShell
# to reflect changes. Try to start from .lnk in the Start Menu or
# fallback to cmd.exe.
# We try the .lnk first because it can have environmental data attached
# to it like fonts, colors, etc.
[System.Reflection.Assembly]::LoadWithPartialName("System.Diagnostics")
$dest = Split-Path $PROFILE -Parent
Copy-Item "*.ps1" $dest -Confirm -Exclude "publish.ps1"
# 1) Get .lnk to PowerShell
# Locale Start Menu name?...
$SM = [System.Environment+SpecialFolder]::StartMenu
$CurrentUserStartMenuPath = $([System.Environment]::GetFolderPath($SM))
$StartMenuName = Split-Path $CurrentUserStartMenuPath -Leaf
# Common Start Menu path?...
$CAD = [System.Environment+SpecialFolder]::CommonApplicationData
$allUsersPath = Split-Path $([System.Environment]::GetFolderPath($CAD)) -Parent
$AllUsersStartMenuPath = Join-Path $allUsersPath $StartMenuName
$PSLnkPath = @(Get-ChildItem $AllUsersStartMenuPath, $CurrentUserStartMenuPath `
-Recurse -Include "Windows PowerShell.lnk")
# 2) Restart...
# Is PowerShell available in PATH?
if ( Get-Command "powershell.exe" -ErrorAction SilentlyContinue ) {
if ($PSLnkPath) {
$pi = New-Object "System.Diagnostics.ProcessStartInfo"
$pi.FileName = $PSLnkPath[0]
$pi.UseShellExecute = $true
# See "powershell -help" for info on -Command
$pi.Arguments = "-NoExit -Command Set-Location $PWD"
[System.Diagnostics.Process]::Start($pi)
}
else {
# See "powershell -help" for info on -Command
cmd.exe /c start powershell.exe -Command { Set-Location $PWD } -NoExit
}
}
else {
Write-Host -ForegroundColor RED "Powershell not available in PATH."
}
# Let clean up after ourselves...
Stop-Process -Id $PID
Ответ 6
Это только уточнение двух строк script в ответе guillermooo выше, который не получил новое окно PowerShell в правильный каталог для меня. Я считаю, что это связано с тем, что $PWD оценивается в новом окне окна PowerShell, который не является значением, которое мы хотим, чтобы процесс установки был обработан.
function Restart-Ps {
$cline = "`"/c start powershell.exe -noexit -c `"Set-Location '{0}'" -f $PWD.path
cmd $cline
Stop-Process -Id $PID
}
По правде, он не должен работать, так как из командной строки, который он выплевывает, является неправильным, но, похоже, это делает работу и это достаточно хорошо для меня.