How to reload user profile from script file in PowerShell

PowershellProfile

Powershell Problem Overview


I want to reload my user profile from a script file. I thought that dot sourcing it from within the script file would do the trick, but it doesn't work:

# file.ps1
. $PROFILE

However, it does work if I dot source it from PowerShell's interpreter.

Why do I want to do this?

I run this script every time I update my profile and want to test it, so I'd like to avoid having to restart PowerShell to refresh the environment.

Powershell Solutions


Solution 1 - Powershell

If you want to globally refresh your profile from a script, you will have to run that script "dot-sourced".

When you run your script, all the profile script runs in a "script" scope and will not modify your "global" scope.

In order for a script to modify your global scope, it needs to be "dot-source" or preceded with a period.

. ./yourrestartscript.ps1

where you have your profile script "dot-sourced" inside of "yourrestartscript.ps1". What you are actually doing is telling "yourrestartscript" to run in the current scope and inside that script, you are telling the $profile script to run in the script's scope. Since the script's scope is the global scope, any variables set or commands in your profile will happen in the global scope.

That doesn't buy you much advantage over running

. $profile

Solution 2 - Powershell

So, the approach that you marked as the answer may work inside the Powershell command prompt, but it doesn't work inside PowerShell ISE (which, to me, provides a superior PowerShell session) and probably won't work right in other PowerShell environments.

Here's a script that I have been using for a while, and it has worked very well for me in every environment. I simply put this function into my Profile.ps1 at ~\Documents\WindowsPowerShell, and whenever I want to reload my profile, I dot-source the function, i.e.

. Reload-Profile

Here's the function:

function Reload-Profile {
    @(
        $Profile.AllUsersAllHosts,
        $Profile.AllUsersCurrentHost,
        $Profile.CurrentUserAllHosts,
        $Profile.CurrentUserCurrentHost
    ) | % {
        if(Test-Path $_){
            Write-Verbose "Running $_"
            . $_
        }
    }	 
}

Solution 3 - Powershell

& $profile   

works to reload the profile.

If your profile sets aliases or executes imports which fail then you will see errors because they were already set in the previous loading of the profile.

Solution 4 - Powershell

Why are you trying to do this?

Because it is likely to create duplicates (appends to $env:path) and problems with setting constant/readonly objects causing errors.

There was a thread on this topic recently on microsoft.public.windows.powershell.

If you are trying to reset the state of the session there is no way to do this, even using an inner scope ($host.EnterNestedPrompt()) because of the ability to set variables/aliases/... at "all scope".

Solution 5 - Powershell

I found this workaround:

#some-script.ps1




#restart profile (open new powershell session)
cmd.exe /c start powershell.exe -c { Set-Location $PWD } -NoExit
Stop-Process -Id $PID

#restart profile (open new powershell session) cmd.exe /c start powershell.exe -c { Set-Location $PWD } -NoExit Stop-Process -Id $PID

A more elaborated version:

#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.



$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

Stop-Process -Id $PID

Solution 6 - Powershell

This is only a refinement of the two line script in guillermooo's answer above, which did not get the new PowerShell window into the correct directory for me. I believe this is because $PWD is evaluated in the new PowerShell window's context, which is not the value we want set-location to process.

function Restart-Ps {
$cline = "`"/c start powershell.exe -noexit -c `"Set-Location '{0}'" -f $PWD.path
cmd $cline
Stop-Process -Id $PID
}

By rights it shouldn't work, as the command line it spits out is malformed, but it seems to do the job and that's good enough for me.

Solution 7 - Powershell

since I stumbled onto this several years later, I thought to add that you can use the invocation operator: & to load your profile with the default variable to your profile: $profile.

so, if your session somehow fails to load your profile (happens to me with cmder/conemu) just type:

& $profile

Solution 8 - Powershell

I used this to troubleshoot what profile was taking forever to load.

Start Run:

powershell_ise -noprofile

Then i ran this:

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

Thank you @Winston Fassett for getting me closer to finding my issue.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionguillermoooView Question on Stackoverflow
Solution 1 - PowershellSteven MurawskiView Answer on Stackoverflow
Solution 2 - PowershellWinston FassettView Answer on Stackoverflow
Solution 3 - PowershellLahruView Answer on Stackoverflow
Solution 4 - PowershellRichardView Answer on Stackoverflow
Solution 5 - PowershellguillermoooView Answer on Stackoverflow
Solution 6 - PowershellAlexView Answer on Stackoverflow
Solution 7 - PowershelldanwalterlinkView Answer on Stackoverflow
Solution 8 - PowershellOmzigView Answer on Stackoverflow