L'omniprésent script posté à l'origine par Jeffrey Snover de l'équipe PowerShell (donnée dans La réponse de Skyler ) et les variations postées par Keith Cedirc, et EBGreen, souffrent toutes d'un sérieux inconvénient-- le fait que le code rapporte ce que vous attendez dépend de l'endroit où vous l'appelez !
Mon code ci-dessous résout ce problème en référençant simplement script au lieu de parent l'étendue :
function Get-ScriptDirectory
{
Split-Path $script:MyInvocation.MyCommand.Path
}
Pour illustrer le problème, j'ai créé un véhicule de test qui évalue l'expression cible de quatre manières différentes. (Les termes entre parenthèses sont les clés du tableau de résultats suivant).
- code en ligne [en ligne]
- fonction inline, c'est-à-dire fonction dans le programme principal [fonction inline].
- Fonction "dot-sourced", c'est-à-dire que la même fonction est déplacée dans un fichier .ps1 distinct [dot source].
- Fonction de module, c'est-à-dire la même fonction déplacée dans un fichier .psm1 distinct [module].
Les deux dernières colonnes montrent le résultat de l'utilisation de la portée script (c'est-à-dire $script :) ou avec la portée parent (avec -scope 1). Un résultat de "script" signifie que l'invocation a correctement signalé l'emplacement du script. Le résultat "module" signifie que l'invocation a signalé l'emplacement du module contenant la fonction plutôt que le script qui a appelé la fonction ; cela indique un inconvénient des deux fonctions, à savoir que vous ne pouvez pas placer la fonction dans un module.
Si l'on met de côté la question du module, l'observation remarquable du tableau est que L'utilisation de l'approche de la portée parentale échoue la plupart du temps. (en fait, deux fois plus souvent qu'elle ne réussit).
Enfin, voici le véhicule d'essai :
function DoubleNested()
{
"=== DOUBLE NESTED ==="
NestCall
}
function NestCall()
{
"=== NESTED ==="
"top level:"
Split-Path $script:MyInvocation.MyCommand.Path
#$foo = (Get-Variable MyInvocation -Scope 1).Value
#Split-Path $foo.MyCommand.Path
"immediate func call"
Get-ScriptDirectory1
"dot-source call"
Get-ScriptDirectory2
"module call"
Get-ScriptDirectory3
}
function Get-ScriptDirectory1
{
Split-Path $script:MyInvocation.MyCommand.Path
# $Invocation = (Get-Variable MyInvocation -Scope 1).Value
# Split-Path $Invocation.MyCommand.Path
}
. .\ScriptDirFinder.ps1
Import-Module ScriptDirFinder -force
"top level:"
Split-Path $script:MyInvocation.MyCommand.Path
#$foo = (Get-Variable MyInvocation -Scope 1).Value
#Split-Path $foo.MyCommand.Path
"immediate func call"
Get-ScriptDirectory1
"dot-source call"
Get-ScriptDirectory2
"module call"
Get-ScriptDirectory3
NestCall
DoubleNested
Contenu de ScriptDirFinder.ps1 :
function Get-ScriptDirectory2
{
Split-Path $script:MyInvocation.MyCommand.Path
# $Invocation = (Get-Variable MyInvocation -Scope 1).Value
# Split-Path $Invocation.MyCommand.Path
}
Contenu de ScriptDirFinder.psm1 :
function Get-ScriptDirectory3
{
Split-Path $script:MyInvocation.MyCommand.Path
# $Invocation = (Get-Variable MyInvocation -Scope 1).Value
# Split-Path $Invocation.MyCommand.Path
}
Je ne suis pas au courant de ce qui a été introduit dans PowerShell 2, mais il se pourrait très bien que la portée script n'existait pas dans PowerShell 1, au moment où Jeffrey Snover a publié son exemple.
J'ai été surpris quand, bien que j'aie trouvé son exemple de code proliférant partout sur le web, il a échoué immédiatement quand je l'ai essayé ! Mais c'était parce que je l'ai utilisé différemment de l'exemple de Snover (je ne l'ai pas appelé au script-top mais à l'intérieur d'une autre fonction (mon exemple "imbriqué deux fois")).
Mise à jour 2011.09.12
Vous pouvez lire ce sujet, ainsi que d'autres conseils et astuces sur les modules, dans mon article qui vient d'être publié sur Simple-Talk.com : Plus loin dans le terrier du lapin : modules PowerShell et encapsulation .
0 votes
Et les chemins fixes ne sont pas fiables si l'utilisateur installe le logiciel ailleurs que là où vous l'attendiez...
3 votes
Ummm.... ma question a été marquée comme étant un doublon d'une question posée presque exactement deux ans auparavant. après le mien ? WTF ?
1 votes
On peut dire que ce n'est pas la bonne façon de faire la duplication - en général, la question la plus ancienne devrait être la question principale (canonique). La question de savoir si cela vaut la peine d'être corrigé est moins claire - demandez peut-être à la MSO. Je note que le doublon est lui-même marqué comme un doublon possible d'une question de type troisième question qui a également été posée après celle-ci.