Quelle est la meilleure façon de déterminer l'emplacement du script PowerShell actuel?

chaque fois que j'ai besoin de faire référence à un module ou un script commun, j'aime utiliser des chemins relatifs au fichier de script courant, de cette façon, mon script peut toujours trouver d'Autres scripts dans la bibliothèque.

alors, quelle est la meilleure façon standard de déterminer le répertoire du script actuel? Actuellement, je fais:

$MyDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition)

je sais en modules.psm1) vous pouvez utiliser $PSScriptRoot pour obtenir cette information, mais cela n'est pas défini dans les scripts réguliers (i.e. .ps1).

Quelle est la façon canonique d'obtenir l'emplacement actuel du fichier de script PowerShell?

379
demandé sur Servy 2011-03-29 03:46:30

11 réponses

PowerShell 3+

# This is an automatic variable set to the current file's/module's directory
$PSScriptRoot

PowerShell 2

avant PowerShell 3, Il n'y avait pas de meilleur moyen que de MyInvocation.MyCommand.Definition propriété pour les scripts généraux. J'ai eu l' la ligne suivante au sommet de chaque script powershell que j'ai eu:

$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
642
répondu JaredPar 2017-05-23 12:34:53

si vous créez un Module V2, vous pouvez utiliser une variable automatique appelée $PSScriptRoot .

de PS > Help automatic_variable

$PSScriptRoot
       Contains the directory from which the script module is being executed.
       This variable allows scripts to use the module path to access other
       resources.
49
répondu Andy Schneider 2014-05-19 01:38:39

Pour PowerShell 3.0

$PSCommandPath
    Contains the full path and file name of the script that is being run. 
    This variable is valid in all scripts.

la fonction est alors:

function Get-ScriptDirectory {
    Split-Path -Parent $PSCommandPath
}
24
répondu CodeMonkeyKing 2014-05-19 01:39:34

peut-être que je rate quelque chose ici... mais si vous voulez le répertoire de travail actuel, vous pouvez simplement utiliser ceci: (Get-Location).Path pour une chaîne de caractères, ou Get-Location pour un objet.

sauf si vous faites référence à quelque chose comme ça, ce que je comprends après avoir relu la question.

function Get-Script-Directory
{
    $scriptInvocation = (Get-Variable MyInvocation -Scope 1).Value
    return Split-Path $scriptInvocation.MyCommand.Path
}
13
répondu Sean C. 2011-03-29 00:06:33

j'utilise le variable automatique $ExecutionContext, il travaille à partir de PowerShell 2 et plus tard.

$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath('.\')

$ExecutionContext Contient un objet Motorintrinsics qui représente contexte d'exécution de L'hôte PowerShell de Windows. Vous pouvez utilisez cette variable pour trouver les objets d'exécution qui sont disponible pour les applets de commande.

8
répondu Viggos 2018-03-11 04:49:20

j'avais besoin de savoir le nom du script et d'où il est exécuté.

préfixe "$global: "à la structure MyInvocation renvoie le nom complet du chemin et du script lorsqu'il est appelé à partir du script principal et de la ligne principale d'un importé .PSM1 fichier de bibliothèque. Il fonctionne également à partir d'une fonction dans une bibliothèque importée.

après avoir beaucoup tripoté, j'ai décidé d'utiliser $global:MyInvocation.InvocationName. Il fonctionne de manière fiable avec CMD lancer, exécuter Avec Powershell, et L'ISE. Les lancements locaux et UNC renvoient le bon chemin.

6
répondu Bruce Gavin 2014-05-12 22:21:24

m'a pris un certain temps pour développer quelque chose qui a pris la réponse acceptée et l'a transformée en une fonction robuste.

pas sûr pour les autres, mais je travaille dans un environnement avec des machines sur les versions 2 et 3 de PowerShell, donc j'ai eu besoin de gérer les deux. La fonction suivante offre un repli gracieux:

Function Get-PSScriptRoot
{
    $ScriptRoot = ""

    Try
    {
        $ScriptRoot = Get-Variable -Name PSScriptRoot -ValueOnly -ErrorAction Stop
    }
    Catch
    {
        $ScriptRoot = Split-Path $script:MyInvocation.MyCommand.Path
    }

    Write-Output $ScriptRoot
}

cela signifie également que la fonction se réfère à la portée du Script plutôt que la portée du parent comme souligné par Michael Sorens dans son blog

6
répondu Bruno 2016-04-09 13:21:02

très similaire aux réponses déjà publiées, mais la tuyauterie semble PLUS PS-like.

$PSCommandPath | Split-Path -Parent
5
répondu CPAR 2016-10-13 20:45:26

Pour Powershell 3+

function Get-ScriptDirectory {
    if ($psise) {Split-Path $psise.CurrentFile.FullPath}
    else {$global:PSScriptRoot}
}

j'ai placé cette fonction dans mon profil. Fonctionne dans ISE en utilisant la sélection F8/Run aussi.

4
répondu nickkzl 2017-01-27 09:32:10

vous pourriez aussi considérer split-path -parent $psISE.CurrentFile.Fullpath si l'une des autres méthodes échoue. En particulier, si vous exécutez un fichier pour charger un tas de fonctions et ensuite exécuter ces fonctions avec-dans le shell ISE (ou si vous exécutez-selected), il semble que la fonction Get-Script-Directory comme ci-dessus ne fonctionne pas.

1
répondu user2023266 2013-01-29 21:44:53
function func1() 
{
   $inv = (Get-Variable MyInvocation -Scope 1).Value
   #$inv.MyCommand | Format-List *   
   $Path1 = Split-Path $inv.scriptname
   Write-Host $Path1
}

function Main()
{
    func1
}

Main
-2
répondu Ravi 2015-04-28 07:47:34