Bagaimana cara mengembalikan nama skrip panggilan dari Modul Powershell?

Saya memiliki dua file Powershell, sebuah modul dan skrip yang memanggil modul.

Modul: test.psm1

Function Get-Info {
    $MyInvocation.MyCommand.Name
}

Skrip: myTest.ps1

Import-Module C:\Users\moomin\Documents\test.psm1 -force
Get-Info

Ketika saya menjalankan ./myTest.ps1 saya mengerti

Get-Info

Saya ingin mengembalikan nama skrip panggilan (test.ps1). Bagaimana saya bisa melakukan itu?


person Mark Allison    schedule 29.04.2014    source sumber
comment
Saya menyadari bahwa ini mungkin hanya latihan akademis untuk Anda, tetapi mengapa tidak memanggil $MyInvocation.MyCommand.Name dari skrip myTest.ps1 untuk mendapatkan info tersebut?   -  person TheMadTechnician    schedule 29.04.2014
comment
Ini bukan latihan akademis. Saya telah memposting kode contoh sederhana untuk membantu penjawab. Saya perlu mendapatkan nama skrip panggilan dari modul.   -  person Mark Allison    schedule 29.04.2014
comment
kemungkinan duplikat Bagaimana saya bisa mendapatkan file eksekusi PowerShell saat ini?   -  person JohnC    schedule 20.04.2015
comment
@JohnC: Pertanyaan ini tentang memanggil skrip, pertanyaan lainnya adalah tentang mengeksekusi file. Misalnya jika main.ps1 memanggil fungsi dari module.psm1, skrip panggilan adalah main.ps1, dan mengeksekusi sctipt adalah module.psm1   -  person Michael Freidgeim    schedule 14.07.2017


Jawaban (9)


Gunakan PSCommandPath sebagai gantinya di modul Anda:
Contoh test.psm1

function Get-Info{
    $MyInvocation.PSCommandPath
}

Contoh myTest.ps1

Import-Module C:\Users\moomin\Documents\test.psm1 -force
Get-Info

Keluaran:

C:\Users\moomin\Documents\myTest.ps1

Kalau mau hanya nama script saja yang bisa dikelola dengan cara melakukan

GCI $MyInvocation.PSCommandPath | Select -Expand Name

Itu akan menghasilkan:

myTest.ps1
person TheMadTechnician    schedule 29.04.2014
comment
Sayangnya, ini berfungsi untuk PSv3+ Fitur Pemuatan Otomatis Modul - person iRon; 19.08.2018

Saya yakin Anda bisa menggunakan cmdlet Get-PSCallStack, yang mengembalikan array objek bingkai tumpukan. Anda dapat menggunakan ini untuk mengidentifikasi skrip panggilan hingga ke baris kode.

Modul: test.psm1

Function Get-Info {
    $callstack = Get-PSCallStack
    $callstack[1].Location
}

Keluaran:

myTest.ps1: Line 2
person James    schedule 30.04.2014

Menggunakan $MyInvocation.MyCommand relatif terhadap cakupannya.

Contoh sederhana (Dari skrip yang terletak: C:\Dev\Test-Script.ps1):

$name = $MyInvocation.MyCommand.Name;
$path = $MyInvocation.MyCommand.Path;

function Get-Invocation(){
   $path = $MyInvocation.MyCommand.Path;
   $cmd = $MyInvocation.MyCommand.Name; 
   write-host "Command : $cmd - Path : $path";
}

write-host "Command : $cmd - Path : $path";
Get-Invocation;

Output saat menjalankan .\c:\Dev\Test-Script.ps1 :

Command : C:\Dev\Test-Script.ps1 - Path : C:\Dev\Test-Script.ps1
Command : Get-Invocation - Path : 

Seperti yang Anda lihat, $MyInvocation relatif terhadap pelingkupan. Jika Anda menginginkan jalur skrip Anda, jangan sertakan dalam suatu fungsi. Jika Anda ingin pemanggilan perintah, maka bungkuslah.

Anda juga bisa menggunakan callstack seperti yang disarankan, namun perhatikan aturan pelingkupan.

person Harald F.    schedule 30.04.2014

Saya menggunakan ini hari ini setelah mencoba beberapa teknik.

$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$ScriptName = $MyInvocation.MyCommand | select -ExpandProperty Name
Invoke-Expression ". $Script\$ScriptName"
person BeastianSTi    schedule 17.10.2014

Untuk merujuk ke info pemanggilan skrip panggilan, gunakan:

@(Get-PSCallStack)[1].InvocationInfo

e.g.:

@(Get-PSCallStack)[1].InvocationInfo.MyCommand.Name
person iRon    schedule 21.12.2017

Ini memberikan jalur skrip dengan garis miring terbalik sebagai satu variabel dan nama skrip sebagai variabel lainnya.

Jalur ini berfungsi dengan Powershell 2.0 dan 3.0 dan 4.0 dan mungkin 5.0 Dimana dengan Posershell $PSscriptroot sekarang tersedia.

$_INST = $myinvocation.mycommand.path.substring(0,($myinvocation.mycommand.path.length - $MyInvocation.mycommand.name.length))

$_ScriptName = $myinvocation.mycommand.path.substring($MyInvocation.MyCommand.Definition.LastIndexOf('\'),($MyInvocation.mycommand.name.length +1))

$_ScriptName = $_ScriptName.TrimStart('\')

person DeployGuy    schedule 10.04.2015

Jika Anda menginginkan pendekatan yang lebih dapat digunakan kembali, Anda dapat menggunakan:

function Get-CallingFileName
{
    $cStack = @(Get-PSCallStack)
    $cStack[$cStack.Length-1].InvocationInfo.MyCommand.Name
}

Tantangan yang saya hadapi adalah memiliki fungsi yang dapat digunakan kembali dalam modul. Segala sesuatu yang lain berasumsi bahwa skrip memanggil fungsi modul secara langsung dan jika dihapus bahkan 1 langkah, maka hasilnya adalah nama file modul. Namun, jika skrip sumber memanggil fungsi dalam modul yang pada gilirannya memanggil fungsi lain dalam modul, maka ini adalah satu-satunya jawaban yang saya lihat yang dapat memastikan Anda mendapatkan info skrip sumber.

Tentu saja, pendekatan ini didasarkan pada apa yang diposting oleh @iRon dan @James.

person Josh Bailey    schedule 02.10.2019

Bagi Anda para Googler yang mencari solusi salin tempel cepat, inilah yang berfungsi di Powershell 5.1

Di dalam modul Anda:

$Script = (Get-PSCallStack)[2].Command

Ini hanya akan menampilkan nama skrip (ScriptName.ps1) yang memanggil fungsi yang terletak di modul.

person metablaster    schedule 23.12.2019

Saya menggunakan ini di modul saya:

function Get-ScriptPath {
    [CmdletBinding()]
    param (
        [string]
        $Extension = '.ps1'
    )

    # Allow module to inherit '-Verbose' flag.
    if (($PSCmdlet) -and (-not $PSBoundParameters.ContainsKey('Verbose'))) {
        $VerbosePreference = $PSCmdlet.GetVariableValue('VerbosePreference')
    }

    # Allow module to inherit '-Debug' flag.
    if (($PSCmdlet) -and (-not $PSBoundParameters.ContainsKey('Debug'))) {
        $DebugPreference = $PSCmdlet.GetVariableValue('DebugPreference')
    }
    
    $callstack = Get-PSCallStack

    $i = 0
    $max = 100

    while ($true) {
        if (!$callstack[$i]) {
            Write-Verbose "Cannot detect callstack frame '$i' in 'Get-ScriptPath'."
            return $null
        }

        $path = $callstack[$i].ScriptName

        if ($path) {
            Write-Verbose "Callstack frame '$i': '$path'."
            $ext = [IO.Path]::GetExtension($path)
            if (($ext) -and $ext -eq $Extension) {
                return $path
            }
        }

        $i++

        if ($i -gt $max) {
            Write-Verbose "Exceeded the maximum of '$max' callstack frames in 'Get-ScriptPath'."
            return $null
        }
    }

    return $null
}
person Alek Davis    schedule 15.08.2020