Como posso encontrar o caminho de origem de um script de execução? [duplicado]
-
03-07-2019 - |
Pergunta
Esta questão já tem uma resposta aqui:
Eu quero ser capaz de dizer o caminho que o meu script execução foi executado a partir.
Isso muitas vezes não vai ser de US $ pwd.
Eu preciso chamar outros scripts que estão em uma estrutura de pastas em relação ao meu script e enquanto eu poderia codificar os caminhos, que é tanto mau gosto e um pouco de dor no pescoço ao tentar promover a partir de "dev" para " teste" para "produção".
Solução
O script onipresente Postado Originalmente por Jeffrey Snover da equipe PowerShell (dada em de Skyler resposta ) e as variações postados por Keith Cedirc e EBGreen, todos sofrem de uma séria desvantagem! - se os relatórios de código que você espera depende de onde você chamá-lo
Meu código abaixo ultrapassa este problema simplesmente fazendo referência roteiro escopo em vez de pai escopo:
function Get-ScriptDirectory
{
Split-Path $script:MyInvocation.MyCommand.Path
}
Para ilustrar o problema, eu criei um veículo de teste que evalutes a expressão alvo de quatro maneiras diferentes. (Os termos entre parênteses são as chaves para a tabela de resultados seguinte.)
- código embutido [linha]
- função inline, função ou seja, no programa principal [função inline] função
- Dot-sourced, ou seja, a mesma função mudou-se para um arquivo .ps1 separado [fonte dot]
- função do módulo, isto é, a mesma função transferida para um ficheiro separado .psm1 [módulo]
As duas últimas colunas mostram o resultado do uso escopo do script (ou seja, $ script :) ou com escopo pai (com -scope 1). Um resultado de meios "roteiro" que a invocação relatados corretamente a localização do script. "Módulo" significa resultado da invocação relatou a localização do módulo que contém a função, em vez do script que chamou a função; isso indica uma desvantagem de ambas as funções que você não pode colocar a função em um módulo.
Definindo a questão módulo de lado a observação notável da mesa é que usando a abordagem de escopo pai falhar na maioria das vezes (na verdade, duas vezes mais que ele consegue).
Finalmente, aqui é o veículo de teste:
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
Conteúdo do ScriptDirFinder.ps1:
function Get-ScriptDirectory2
{
Split-Path $script:MyInvocation.MyCommand.Path
# $Invocation = (Get-Variable MyInvocation -Scope 1).Value
# Split-Path $Invocation.MyCommand.Path
}
Conteúdo do ScriptDirFinder.psm1:
function Get-ScriptDirectory3
{
Split-Path $script:MyInvocation.MyCommand.Path
# $Invocation = (Get-Variable MyInvocation -Scope 1).Value
# Split-Path $Invocation.MyCommand.Path
}
Eu não estou familiarizado com o que foi introduzido em PowerShell 2, mas poderia muito bem ser que escopo do script não existia no PowerShell 1, no momento Jeffrey Snover publicou seu exemplo.
Eu fiquei surpreso quando, embora eu achei o seu exemplo de código proliferaram por toda parte na web, ele falhou imediatamente quando eu tentei! Mas isso foi porque eu usei-o de forma diferente do que o exemplo de Snover (I chamado não no script do topo, mas a partir de dentro de outra função (meu "nested duas vezes" exemplo).)
2011/09/12 Atualização
Você pode ler sobre isso com outras dicas e truques sobre módulos em meu artigo recém-publicado sobre Simple-Talk.com: Outras Down the Rabbit Hole:. PowerShell Módulos e Encapsulation
Outras dicas
Você marcado sua pergunta para PowerShell versão 1.0, no entanto, se você tem acesso ao PowerShell versão 3.0 você sabe tem $PSCommandPath
and$PSScriptRoot
which faz começar o caminho do script um pouco mais fácil. Consulte a "outro script CARACTERÍSTICAS", nesta página para mais informações.
Estamos usando código como este na maioria dos nossos roteiros para vários anos sem problemas:
#--------------------------------------------------------------------
# Dot source support scripts
#--------------------------------------------------------------------
$ScriptPath = $MyInvocation.MyCommand.Path
$ScriptDir = Split-Path -Parent $ScriptPath
. $ScriptDir\BuildVars.ps1
. $ScriptDir\LibraryBuildUtils.ps1
. $ScriptDir\BuildReportUtils.ps1
Eu corri para o mesmo problema recentemente. O seguinte artigo me ajudou a resolver o problema: http: // blogs.msdn.com/powershell/archive/2007/06/19/get-scriptdirectory.aspx
Se você não está interessado em saber como ele funciona, aqui está todo o código que você precisa pelo artigo:
function Get-ScriptDirectory
{
$Invocation = (Get-Variable MyInvocation -Scope 1).Value
Split-Path $Invocation.MyCommand.Path
}
E então você começa o caminho, basta fazer:
$path = Get-ScriptDirectory
Eu acho que você pode encontrar o caminho do script em execução usando
$MyInvocation.MyCommand.Path
Espero que ajude!
Cédric
Este é um daqueles esquisitices (a minha mente pelo menos) em PS. Tenho certeza de que há uma boa razão para isso, mas ainda parece estranho para mim. Assim:
Se você estiver em um script, mas não em uma função, em seguida $ myInvocation.InvocationName lhe dará o caminho completo, incluindo o nome do script. Se você estiver em um script e dentro de uma função, em seguida $ myInvocation.ScriptName vai dar-lhe a mesma coisa.
Obrigado msorens! Isso realmente me ajudou com o meu módulo personalizado. No caso de alguém está interessado em fazer a sua própria, é aqui como meu está estruturado.
MyModule (folder)
- MyModule.psd1 (help New-ModuleManifest)
- MyScriptFile.ps1 (ps1 files are easy to test)
Você, então, referência MyScriptFile.ps1 em MyModule.psd1. Referenciando o .ps1 na matriz NestedModules colocará as funções no estado da sessão módulo em vez do estado da sessão global. ( Como escrever um módulo Manifest )
NestedModules = @('.\MyScriptFile.ps1','.\MyOtherScriptFile.ps1')
Conteúdo de MyScriptFile.ps1
function Get-ScriptDirectory {
Split-Path $script:MyInvocation.MyCommand.Path
}
try {
Export-ModuleMember -Function "*-*"
}
catch{}
As peles try / catch o erro do Export-ModuleMember ao executar MyScriptFile.ps1
Copie o MyModule para um dos caminhos encontrados aqui $ env: PSModulePath
PS C:\>Import-Module MyModule
PS C:\>Get-Command -Module MyModule
CommandType Name ModuleName
----------- ---- ----------
Function Get-ScriptDirectory MyModule