Ответ 1
Вездесущий script изначально размещенный Джеффри Сновер команды PowerShell (данный в Skyler answer), а вариации, опубликованные Keith Cedirc и EBGreen, страдают от серьезного недостатка - независимо от того, сообщает ли код, что вы ожидаете, от того, где вы его называете!
Мой код ниже преодолевает эту проблему, просто ссылаясь на область script вместо parent:
function Get-ScriptDirectory
{
Split-Path $script:MyInvocation.MyCommand.Path
}
Чтобы проиллюстрировать проблему, я создал тестовое средство, которое анализирует целевое выражение четырьмя различными способами. (В скобках указаны ключи к следующей таблице результатов.)
- встроенный код [inline]
- встроенная функция, т.е. функция в основной программе [встроенная функция]
- Функция Dot-sourced, т.е. одна и та же функция переместилась в отдельный файл .ps1 [источник точки]
- Функция модуля, т.е. одна и та же функция переместилась в отдельный файл .psm1 [module]
Последние два столбца показывают результат использования области script (т.е. $script:) или с родительской областью (с -scope 1). Результат "script" означает, что обращение правильно сообщило о местоположении script. Результат "модуля" означает, что вызов сообщил местоположение модуля, содержащего функцию, а не script, который вызвал функцию; это указывает на недостаток обеих функций, которые вы не можете поместить в модуль.
Установка проблемы с модулем в сторону замечательного наблюдения из таблицы заключается в том, что с использованием подхода родительской области не выполняется большую часть времени (фактически, в два раза чаще, чем это удается).
Наконец, вот тестовое транспортное средство:
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
Содержание ScriptDirFinder.ps1:
function Get-ScriptDirectory2
{
Split-Path $script:MyInvocation.MyCommand.Path
# $Invocation = (Get-Variable MyInvocation -Scope 1).Value
# Split-Path $Invocation.MyCommand.Path
}
Содержимое ScriptDirFinder.psm1:
function Get-ScriptDirectory3
{
Split-Path $script:MyInvocation.MyCommand.Path
# $Invocation = (Get-Variable MyInvocation -Scope 1).Value
# Split-Path $Invocation.MyCommand.Path
}
Я не знаком с тем, что было введено в PowerShell 2, но вполне возможно, что область script не существовала в PowerShell 1, в то время, когда Джеффри Сноувер опубликовал свой пример.
Я был удивлен, когда, хотя я нашел, что его пример кода широко распространен в Интернете, он сразу же удался, когда я попробовал! Но это было потому, что я использовал его по-другому, чем пример Snover (я назвал его не в script -top, а изнутри другой функции (мой пример "вложенной дважды" ).
2011.09.12 Обновление
Вы можете прочитать об этом с другими советами и трюками по модулям в моей только что опубликованной статье на Simple-Talk.com: Дальше вниз по кроличьей дыре: модули и инкапсуляция PowerShell.