刷新/重启 PowerShell 会话而不退出

61

我一直在调整PowerShell配置文件中的一些脚本,但每次退出PowerShell再重新启动它来加载我对配置文件中脚本所做的更改变得很烦。有没有可能在不退出的情况下重启PowerShell会话?


2
计划功能:https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/13390179-powershell-ise-does-not-have-the-ability-to-restart - JohnLBevan
这仅适用于 ISE。 - spicy.dll
9个回答

29

您可以使用. $profile来重新加载配置文件。


1
如果您要更新的内容不是C:\Users\wombat\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1,请指定一个配置文件。 - EBGreen
7
'C:\Users\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1' 这个术语无法识别为命令、函数、脚本文件或可操作程序的名称。请检查名称的拼写,如果包含路径,请验证路径是否正确,然后重试。 位于第1行字符2
  • . <<<< $profile
    • CategoryInfo : ObjectNotFound: (C:\Users\nrp023...ell_profile.p s1:String) [], CommandNotFoundException
    • FullyQualifiedErrorId : CommandNotFoundException
- shreddish
1
当你说你正在调整一些配置文件中的脚本时,你具体是在调整哪个文件? - EBGreen
2
这并不会以任何方式重置实际的会话变量、已加载的模块等。被投票否定。 - Casper Leon Nielsen
@shreddish,你需要先创建$profile,可以在PowerShell中执行new-item -path $profile -itemtype file来创建。至少我认为这是问题所在。 - mooper
5
这不会刷新会话。您定义的任何变量仍将存在于先前命令中。 - Kellen Stuart

16

这将启动一个新的会话,在同一控制台窗口中重新加载您的配置文件:

Invoke-Command { & "powershell.exe" } -NoNewScope # PowerShell 5
Invoke-Command { & "pwsh.exe"       } -NoNewScope # PowerShell 7

或者使用一个更长但更健壮的命令,以下命令应该可以正确地跨版本工作:

Get-Process -Id $PID | Select-Object -ExpandProperty Path | ForEach-Object { Invoke-Command { & "$_" } -NoNewScope }

当然,您将失去之前会话中的所有变量等。

注意:在同一窗口中创建新会话会使父进程在后台运行。 通常,这不是问题,因为当窗口关闭时,父进程(以及任何其他祖先)将终止。 如果这是一个问题,您可能希望向您的配置文件添加以下内容:

$p = Get-Process -Id $PID
If ($p.Parent.Name -eq $p.Name -and !($p.MainWindowTitle))
{
    Stop-Process -Id $p.Parent.Id -Force
}

1
不重新加载环境变量 - Siraj Kakeh
当我尝试运行这个命令(无论是在编辑器内部还是将其粘贴到控制台中),它会“挂起”PowerShell ISE(也就是说,运行按钮变灰,停止按钮变红)。 - George 2.0 Hope
@George 2.0 希望与 VS Code 不同,PowerShell ISE 中的命令窗口不是一个单独的进程,因此如果不打开新实例,你将很难启动新会话。PowerShell ISE 已不再进行主动功能开发,所以不要指望这种情况会在短时间内改变。 - nmbell
我发现这个解决方案是因为我试图在我的profile.ps1文件中创建一个别名,以便在对其进行更改时重新加载我的配置文件。这是我找到的唯一可以从别名中运行并更新和重新加载会话的解决方案。已点赞,非常感谢! - Gharbad The Weak
我刚刚在之前的 pwsh 上面得到了一个新的 pwsh,我可以使用 exit 命令返回到之前的 pwsh。 - c z
显示剩余3条评论

7
@manojlds的回答是正确的,但它可能会导致错误。例如,如果您在个人资料中定义了一个新的PSDrive,则重新引用它可能会导致错误。
另一种方法是首先启动PowerShell,然后通过键入PowerShell立即在其中启动另一个版本。我在嵌套控制台中进行我的配置更改,退出后再次运行PowerShell以测试更新的配置文件。
另一件事 - 慢慢仔细地进行配置文件更改。在我看来,虽然配置文件确实需要发展,但这种演变通常应该很缓慢。YMMV!

1
对于那些有兴趣尝试的人,实际语法是 powershell(<yourcommandhere>) - JackChance

5
您可以编写一个简单的函数,并将其添加到您的$profile中(或者编写一个模块,然后导入到'$profile'中),例如:
function Restart-PowerShell{
    Start-Process PowerShell # Launch PowerShell host in new window
    exit # Exit existing PowerShell host window
}
# Add any alias if you want, for ex. rps (rp already occupied by "Remove-ItemProperty”)
Set-Alias -Name rps -Value Restart-PowerShell

注意:虽然这可能不完全符合你在问题标题中写的“不退出”的要求,但如果实质上你的本意是想要一些重新启动PowerShell主机命令(默认情况下在PS不可用),那么这个方法可以起到作用...


4
这里的真正答案是“开始PowerShell”,但请注意您将丢失窗口设置。 - Andrew
1
要关闭旧的 shell 并启动一个新的 shell,输入 "exit start powershell",但是正如 Andrew 指出的那样,之前的设置将不会保留。 - cyber101

1
这里是对@Bad答案的扩展。现在它可以处理ISE(因为我经常使用它)。
如果你在ISE中,它将重新启动ISE。如果你在普通的PowerShell中,它将重新启动普通的PowerShell。Get-PSHostProcessInfo返回当前PowerShell会话的信息,允许你确定是否正在运行ISE或不是。
function Restart-PowerShell
{
    if((Get-PSHostProcessInfo).ProcessName.Contains('powershell_ise'))
    {
        Start-Process 'powershell_ise.exe'
    } else {
        Start-Process 'powershell.exe'
    }
    exit
}

Get-PSHostProcessInfo 返回所有当前运行实例的信息,因此如果您从普通控制台而不是 ISE 中调用它,则可能会出现错误。您可以考虑使用 $host.Name 代替,它应该返回您正在使用的进程名称。类似这样:if ((Get-Process -id $pid).ProcessName.contains("powershell_ise"))... 或者稍微改变一下,像这样:if ($host.Name -imatch "ise")... - Randall Borck
@RandallBorck 感谢您的建议!如果您已经测试过这个,您可以编辑我的答案。 - Kellen Stuart

0
在profile.ps1中粘贴以下内容。只需键入reload,它将简单地重新加载/重启。
function reload-Console {
    clear
    Write-Host "Reload Console"
    Get-Process -Id $PID | Select-Object -ExpandProperty Path | ForEach-Object { Invoke-Command { & "$_" } -NoNewScope }
}
New-Alias reload reload-Console

0
请注意,manojlds的答案(当前评分最高的答案)可能存在问题,这取决于您的个人资料正在做什么(基本上是:如果它依赖于一个干净的起点)。但我认为它最大的问题是不容易放入一个可以别名的函数中。
因此,我更喜欢类似于nmbell的答案,但要简单得多:
function Reset-Session {
    # store this shell's parent PID for later use
    $parentPID = $PID
    # get the the path of this shell's executable
    $thisExePath = (Get-Process -Id $PID).Path
    # start a new shell, same window
    Start-Process $thisExePath -NoNewWindow
    # stop this shell if it's still alive
    Stop-Process -Id $parentPID -Force
}
# optional
Set-Alias -Name reset -Value Reset-Session

0
我只是在我的$PROFILE中添加了这个小脚本。
function refresh ($command) {
    cls
    pwsh 
    Exit
}

然后只需键入'refresh',你就得到了。
如果你在开头不加'cls',那么之前的所有文本都会保留在控制台中,你将不得不手动输入它。

-1

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community
Refreshenv不是内置的,它是Chocolatey的一部分。 - Pxtl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接