web-dev-qa-db-fra.com

Comment recharger un profil d'utilisateur à partir d'un fichier de script dans PowerShell

Je souhaite recharger mon profil utilisateur à partir d'un fichier de script. Je pensais que le fait de le doter à partir du fichier de script ferait l'affaire, mais cela ne fonctionne pas:

# file.ps1
. $PROFILE

Cependant, cela fonctionne si je le source de l'interpréteur de PowerShell.

Pourquoi est-ce que je veux faire ça?

J'exécute ce script chaque fois que je mets à jour mon profil et que je souhaite le tester. Par conséquent, j'aimerais éviter de redémarrer PowerShell pour actualiser l'environnement.

36
guillermooo

Ainsi, l'approche que vous avez indiquée comme réponse pourrait fonctionner dans l'invite de commande de Powershell, mais ne fonctionne pas dans PowerShell ISE (qui, selon moi, fournit une session PowerShell supérieure) et ne fonctionnera probablement pas dans d'autres environnements PowerShell .

Voici un script que j'utilise depuis longtemps et qui a très bien fonctionné pour moi dans tous les environnements. Je mets simplement cette fonction dans Profile.ps1 dans ~\Documents\WindowsPowerShell, et chaque fois que je veux recharger mon profil, je source la fonction, c.-à-d.

. Reload-Profile

Voici la fonction:

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

Si vous souhaitez actualiser globalement votre profil à partir d'un script, vous devez exécuter ce script "source par points". 

Lorsque vous exécutez votre script, tout le script de profil s'exécute dans une étendue "script" et ne modifie pas votre étendue "globale". 

Pour qu'un script modifie votre portée globale, il doit être "source de points" ou précédé d'un point.

. ./yourrestartscript.ps1

où vous avez votre script de profil "source par points" dans "yourrestartscript.ps1". En réalité, vous dites à "yourrestartscript" de s'exécuter dans la portée actuelle et, à l'intérieur de ce script, vous indiquez au script de profil $ de s'exécuter dans la portée du script. Etant donné que la portée du script est la portée globale, toutes les variables ou commandes de votre profil se produiront dans la portée globale.

Cela ne vous donne pas beaucoup d'avantages par rapport à la course

. $profile
28
Steven Murawski
& $profile   

travaille pour recharger le profil.

Si votre profil définit des alias ou exécute des importations qui échouent, des erreurs apparaissent car elles ont déjà été définies lors du chargement précédent du profil.

5
Lahru

Pourquoi essayez-vous de faire cela?

Parce qu’il est susceptible de créer des doublons (s’ajoute à $ env: path) et des problèmes avec la définition d’objets constants/en lecture seule générant des erreurs.

Il y avait un fil à ce sujet récemment sur Microsoft.public.windows.powershell .

Si vous essayez de réinitialiser l'état de la session, il n'y a aucun moyen de le faire, même en utilisant une portée interne ($Host.EnterNestedPrompt()) en raison de la possibilité de définir des variables/alias/... sur "toute portée".

3
Richard

J'ai trouvé cette solution de contournement:

#some-script.ps1

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

Une version plus élaborée:

#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
2
guillermooo

Il ne s'agit que d'un raffinement du script à deux lignes dans la réponse ci-dessus de guillermooo, qui n'a pas intégré la nouvelle fenêtre PowerShell dans le bon répertoire. Je pense que c'est parce que $ PWD est évalué dans le contexte de la nouvelle fenêtre PowerShell, ce qui n'est pas la valeur que nous voulons que set-location traite.

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

De droit, cela ne devrait pas fonctionner, car la ligne de commande qu’elle crache est mal formée, mais elle semble faire son travail et c’est suffisant pour moi.

0
Alex

plusieurs années plus tard, je suis tombé sur cette question et j'ai pensé ajouter que vous pouvez utiliser l'opérateur d'invocation: & pour charger votre profil avec la variable par défaut de votre profil: $profile.

donc, si votre session ne parvient pas à charger votre profil (cela m’arrive avec cmder/conemu), il suffit de taper:

& $profile

0
Dan W. Link