Как перезагрузить профиль пользователя из файла сценария в PowerShell
-
05-09-2019 - |
Вопрос
Я хочу перезагрузить свой профиль пользователя из файла скрипта.Я думал, что точка, извлекающая его из файла сценария, сделает свое дело, но это не сработало:
# file.ps1
. $PROFILE
Однако это действительно работает, если я использую исходный код из интерпретатора PowerShell.
Почему я хочу это сделать?
Я запускаю этот скрипт каждый раз, когда обновляю свой профиль, и хочу протестировать его, поэтому я хотел бы избежать необходимости перезапускать PowerShell для обновления среды.
Решение
Итак, подход, который вы отметили как ответ, может работать в командной строке Powershell, но он не работает в PowerShell ISE (который, на мой взгляд, обеспечивает улучшенный сеанс PowerShell) и, вероятно, не будет работать должным образом в других средах PowerShell.
Вот скрипт, который я использую уже некоторое время, и он очень хорошо работал у меня в любой среде.Я просто помещаю эту функцию в свой Profile.ps1 по адресу ~\Documents\WindowsPowerShell, и всякий раз, когда я хочу перезагрузить свой профиль, я ставлю точку в исходном коде функции, т. е.
. Reload-Profile
Вот эта функция:
function Reload-Profile {
@(
$Profile.AllUsersAllHosts,
$Profile.AllUsersCurrentHost,
$Profile.CurrentUserAllHosts,
$Profile.CurrentUserCurrentHost
) | % {
if(Test-Path $_){
Write-Verbose "Running $_"
. $_
}
}
}
Другие советы
Если вы хотите глобально обновить свой профиль с помощью скрипта, вам придется запустить этот скрипт "с точечным исходным кодом".
Когда вы запускаете свой скрипт, весь скрипт профиля выполняется в области "script" и не изменяет вашу "глобальную" область.
Для того чтобы скрипт изменил вашу глобальную область видимости, ему должен быть указан "точечный источник" или перед ним должна стоять точка.
. ./yourrestartscript.ps1
где у вас есть скрипт вашего профиля с "точечным исходным кодом" внутри "yourestartscript.ps1".Что вы на самом деле делаете, так это указываете "yourestartscript" на запуск в текущей области видимости, а внутри этого скрипта вы указываете скрипту $profile на запуск в области видимости скрипта.Поскольку область действия скрипта является глобальной, любые переменные или команды в вашем профиле будут выполняться в глобальной области.
Это не дает вам большого преимущества перед бегом
. $profile
& $profile
работает для перезагрузки профиля.
Если ваш профиль устанавливает псевдонимы или выполняет импорт с ошибкой, то вы увидите ошибки, поскольку они уже были установлены при предыдущей загрузке профиля.
Почему ты пытаешься это сделать?
Потому что это, скорее всего, приведет к созданию дубликатов (добавляется к $env: path) и проблемам с установкой объектов constant / readonly, вызывающих ошибки.
Недавно была тема на эту тему на microsoft.общедоступный.windows.powershell.
Если вы пытаетесь сбросить состояние сеанса, это невозможно сделать, даже используя внутреннюю область ($host.EnterNestedPrompt()
) из-за возможности устанавливать переменные / псевдонимы/...на "всем размахе".
Я нашел это обходное решение:
#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's 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's clean up after ourselves...
Stop-Process -Id $PID
Это всего лишь доработка двухстрочного скрипта в ответе guillermooo выше, который не перевел новое окно PowerShell в правильный каталог для меня.Я полагаю, это связано с тем, что $PWD вычисляется в контексте нового окна PowerShell, а это не то значение, которое мы хотим, чтобы set-location обрабатывал.
function Restart-Ps {
$cline = "`"/c start powershell.exe -noexit -c `"Set-Location '{0}'" -f $PWD.path
cmd $cline
Stop-Process -Id $PID
}
По правилам это не должно работать, так как командная строка, которую он выдает, искажена, но, похоже, она справляется со своей задачей, и для меня этого достаточно.
Я использовал это для устранения неполадок, из-за которых загрузка профиля занимала целую вечность.
Начать Выполнять:
powershell_ise -noprofile
Затем я запустил это:
function Reload-Profile {
@(
$Profile.AllUsersAllHosts,
$Profile.AllUsersCurrentHost,
$Profile.CurrentUserAllHosts,
$Profile.CurrentUserCurrentHost
) | % {
if(Test-Path $_){
Write-Verbose "Running $_"
$measure = Measure-Command {. $_}
"$($measure.TotalSeconds) for $_"
}
}
}
. Reload-Profile
Спасибо вам @Winston Fassett за то, что приблизили меня к поиску моей проблемы.
поскольку я наткнулся на это несколько лет спустя, я подумал добавить, что вы можете использовать оператор вызова: &
чтобы загрузить ваш профиль с переменной по умолчанию в ваш профиль: $profile
.
итак, если вашему сеансу каким-то образом не удается загрузить ваш профиль (такое случается со мной с cmder / conemu), просто введите:
& $profile