如何从PowerShell中的脚本文件重新加载用户配置文件

如何从PowerShell中的脚本文件重新加载用户配置文件,powershell,profile,Powershell,Profile,我想从脚本文件重新加载我的用户配置文件。我认为在脚本文件中使用点源代码可以达到目的,但它不起作用: # file.ps1 . $PROFILE 但是,如果我从PowerShell的解释器中点源代码,它确实可以工作 我为什么要这样做? 每次更新配置文件并想对其进行测试时,我都会运行此脚本,因此我希望避免必须重新启动PowerShell来刷新环境。为什么要尝试这样做 因为它可能会创建重复项(附加到$env:path)以及设置常量/只读对象的问题,从而导致错误 最近有一个关于这个话题的帖子 如果您试图

我想从脚本文件重新加载我的用户配置文件。我认为在脚本文件中使用点源代码可以达到目的,但它不起作用:

# file.ps1
. $PROFILE
但是,如果我从PowerShell的解释器中点源代码,它确实可以工作

我为什么要这样做?


每次更新配置文件并想对其进行测试时,我都会运行此脚本,因此我希望避免必须重新启动PowerShell来刷新环境。

为什么要尝试这样做

因为它可能会创建重复项(附加到$env:path)以及设置常量/只读对象的问题,从而导致错误

最近有一个关于这个话题的帖子


如果您试图重置会话状态,则无法执行此操作,即使使用内部作用域(
$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

如果您想从脚本全局刷新您的配置文件,则必须运行该脚本“点源”

运行脚本时,所有概要文件脚本都在“脚本”范围内运行,并且不会修改“全局”范围

为了让脚本修改您的全局范围,它需要是“点源”或前面带有句点

. ./yourrestartscript.ps1
在“yourrestartscript.ps1”中有您的配置文件脚本“dot sourceed”。您实际要做的是告诉“yourrestartscript”在当前范围内运行,在该脚本中,您告诉$profile脚本在脚本的范围内运行。由于脚本的作用域是全局作用域,因此配置文件中的任何变量集或命令都将发生在全局作用域中


与跑步相比,这并没有给你带来多少优势

. $profile

这只是上面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命令提示符内工作,但在Powershell ISE内不工作(对我来说,ISE提供了一个高级Powershell会话)而且在其他PowerShell环境中可能无法正常工作

这是一个我已经使用了一段时间的脚本,它在任何环境中都非常适合我。我只需将此函数放入~\Documents\WindowsPowerShell的我的Profile.ps1中,每当我想重新加载我的配置文件时,我都会点源函数,即

. Reload-Profile
下面是函数:

function Reload-Profile {
    @(
        $Profile.AllUsersAllHosts,
        $Profile.AllUsersCurrentHost,
        $Profile.CurrentUserAllHosts,
        $Profile.CurrentUserCurrentHost
    ) | % {
        if(Test-Path $_){
            Write-Verbose "Running $_"
            . $_
        }
    }    
}
用于重新加载配置文件


如果您的配置文件设置了别名或执行了失败的导入,那么您将看到错误,因为在上次加载配置文件时已经设置了这些错误。

因为几年后我偶然发现了这一点,我想补充一下,您可以使用调用操作符:
&
将带有默认变量的配置文件加载到您的配置文件中:
$profile

因此,如果您的会话以某种方式无法加载您的配置文件(使用cmder/conemu时发生在我身上),只需键入:


和$profile

我用它来解决加载配置文件需要花费很长时间的问题

开始运行:

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让我更接近找到我的问题。

@Steven:如果我把它放进去$在脚本本身的配置文件中,它不起作用。。。这就是我要做的。@scott$profile是特定于shell的配置文件的完整路径。“与运行相比,这并没有给您带来太多优势”,您是在暗示
$个人资料
做同样的事情吗?你能链接到上面的帖子吗?谢谢“但它在PowerShell ISE中不起作用(在我看来,它提供了一个高级PowerShell会话),并且可能在其他PowerShell环境中也不起作用。”也许您可以解释为什么它不起作用,因为ISE旨在提供与PowerShell的对等性。也很难找到在ISE上使用powershell的原因,所以很高兴知道这一点。@Blake:主要原因是ISE如何识别自己,它使用不同的默认配置文件,并且有不同类型的“版本”。可悲的是,它们是对它的存在和IDE的警告。这个函数的名称使用了一个未经批准的动词(我知道,但每当我编辑我的配置文件时,它都会让VSCode唠叨我。ps1)看到关于这个问题的讨论:谢谢,它重新加载配置文件,但是如何摆脱这样的消息“设置变量:无法覆盖变量ts_pass,因为它是只读或常量。位于…\WindowsPowerShell\Microsoft.PowerShell\u profile.ps1:27字符:1“因为它会重新加载常量,我猜
$profile
按预期工作,无需过度复杂化自定义函数。@Leonard
$配置文件
应该是可接受的答案
$配置文件
似乎无法重新加载功能definitions@xdhmoore条件是什么<代码>$配置文件是否重新加载我的功能definitions@Jason首先,它是.NET之前的核心。在这一点上,我记不清还有多少其他事情。但我通过将所有函数定义等放在一个单独的模块中修复了它。然后我卸载然后加载要重新加载的模块。由于某些原因,这对新定义的函数不起作用。这不起作用<代码>&被称为,它为正在执行的命令创建一个新的环境范围。当命令退出时,此环境将被丢弃。这意味着该命令对环境所做的任何更改都将丢失。您必须改用(
)在当前环境中执行命令。@DavidFerenczyRogožan&运算符就像Unix中的子shell?
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