当嵌套在点源调用中时,如何获得调用Class的脚本文件的名称

时间:2019-07-03 13:29:48

标签: powershell

如果我有以下内容(简化的设置)

class.ps1

class Test {
    Test() {
        $MyInvocation | Show-Object
    }

    [void] Call() {
        $MyInvocation | Show-Object
        <# 
           here $MyInvocation.ScriptName, PSCommandPath show main.ps1 NOT 
           util.ps1 even though it is called from Util.ps1 
        #>
    }
}

Util.ps1

Write-Host "Calling from Util.ps1"
$MyInvocation | Show-Object

Function Test-Util {
    [CmdletBinding()]
    Param()

    Write-Host "Calling from Test-Util in Util.ps1"
    $MyInvocation | Show-Object
}

Function Test-Class {
    [CmdletBinding()]
    Param()

    write-host "Testing Class Test from Util.ps1"
    $Test = [Test]::new()
    Write-Host "Testing Class.Call() from Util.ps1"
    $Test.Call()
}

Function Test-SubUtilTest {
    [CmdletBinding()]
    Param()

    Test-SubUtil
}

SubUtil.ps1

Write-Host "Calling from SubUtil.ps1"
$MyInvocation | Show-Object

Function Test-SubUtil {
    [CmdletBinding()]
    Param()

    Write-Host "Calling from Test-Util in Util.ps1"
    $MyInvocation | Show-Object 

    <# 
        here $MyInvocation.ScriptName, PSCommandPath show Util.ps1 NOT 
        main.ps1 as it is called from Util.ps1 
    #>
}

Main.ps1

. C:\Users\jenny\Class.ps1
. C:\Users\jenny\Util.ps1
. C:\Users\jenny\SubUtil.ps1

Write-Host "From Main.ps1"
$MyInvocation | Show-Object

write-host "Calling Test-Util from util.ps1"
Test-Util

Write-Host "Calling Test-Class from util.ps1"
Test-Class

write-host "Calling Test-SubUtil from Util.ps1"
Test-SubUtilTest
  

$ Test = [Test] :: new()

  

$ Test.Call()

都从util.ps1执行

但是$ MyInvocation仅显示main.ps1

我如何从该类的构造方法或其方法之一确定其调用代码源自此类嵌套点源设置中的ps1文件

我尝试将&替换为&。而且我还尝试过将class.ps1的点源移到util.ps1文件中,但它仍然告诉我main.ps1是源。

此外,真实类文件是一个单例文件,旨在用于多个以点为源的util.ps1文件,并且我不确定是否可以在多个文件中以点源形式将同一个类文件点化,每个文件都以点源到main.ps1中。 (不是在本例中将点源移动到单个实用程序文件中有所不同)

最后,我正在使用PowerShellCookbook模块中的Show-Object。

对于基于函数的嵌套调用有效,但不适用于对类的调用

2 个答案:

答案 0 :(得分:2)

您可以使用堆栈来确定调用方:

class Test {
    Test() {
        Get-PSCallStack | Select-Object -First 1 -Skip 1 -ExpandProperty "Location" | Write-Host
    }

    [void] Call() {
        Get-PSCallStack | Select-Object -First 1 -Skip 1 -ExpandProperty "Location" | Write-Host
    }
}

答案 1 :(得分:0)

mhu值得您给予我应得的全部荣誉,并附有正式的答案复选标记。但我想我会将固定的类发布为已实现行为的其他任何碰巧需要做我必须做的事情的人

Enum LogEntryTypes {
    Information
    Error
    Verbose
    Warning
}

Log.psm1

Class Log {
    [string] $Name
    hidden [string] $FullPath 

    hidden Log([string] $Name, [string] $Path) { 
        $this.Name = $Name 
        $this.FullPath = (Join-Path -Path $Path -ChildPath "$($this.Name).log")
    }

    [Log] Start([bool] $Append) {
        if (-not $Append) { remove-item -Path $this.FullPath -Force -Verbose }
        $this.Information("$($this.Name) Logging Started to $($this.FullPath)")
        return $this
    }

    [void] Stop() { $this.Information("$($this.Name) Logging Ended to $($this.FullPath)") }

    Information([string] $Message) { $this.Information($Message,$null) }

    Information([string] $Message, [object] $Data) { $this.Write($Message,$Data,[LogEntryTypes]::Information) }

    Warning([string] $Message) { $this.Warning($Message,$null) }

    Warning([string] $Message, [object] $Data) { $this.Write($Message,$Data,[LogEntryTypes]::Warning) }

    Error([string] $Message) { $this.Error($Message,$null) }

    Error([string] $Message, [object] $Data) { $this.Write($Message,$Data,[LogEntryTypes]::Error) }

    Verbose([string] $Message) { $this.Verbose($Message,$null) }

    Verbose([string] $Message, [object] $Data) { $this.Write($Message,$Data,[LogEntryTypes]::Verbose) }

    [void] hidden Write([string] $Message, [object] $Data, [LogEntryTypes] $EntryType) {
        $Message = $Message -replace '"', '`"'
        "[$($EntryType.ToString().ToUpper())]<$([DateTime]::Now)>:`tMessage->$Message" | Add-Content -Path $this.FullPath
        if ($Data -ne $null) { "[$($EntryType.ToString().ToUpper())]<$([DateTime]::Now)>:`tData->$Data" | Add-Content -Path $this.FullPath }
        "Write-$EntryType `"[$($EntryType.ToString().ToUpper())]<$([DateTime]::Now)>:`tMessage->$Message`"" | Invoke-Expression
        if ($Data -ne $null) { "Write-$EntryType `"[$($EntryType.ToString().ToUpper())]<$([DateTime]::Now)>:`tData->$Data`"" | Invoke-Expression }
    }
}

Logger.ps1

using namespace System.Collections.Generic
using module ".\Log.psm1"

Class Logger {
    hidden static [Dictionary[String,Log]] $_Logger

    static [string] $Path
    static [bool] $Append

    static Logger() { [Logger]::_Logger = [Dictionary[string,Log]]::new() }

    hidden static [string] GetCallingScriptName() { return ((Get-PSCallStack | Where-Object {$_.Location -notlike "$(((Get-PSCallStack | Select-Object -First 1 -ExpandProperty Location) -split "\.ps1")[0])*" } | Select-Object -First 1 -ExpandProperty "Location") -split "\.ps1")[0] }

    static [Log] Get() { return [Logger]::Get($false) }

    static [Log] Get([bool] $Force) {
        $Name = [Logger]::GetCallingScriptName()
        if ($null -eq [Logger]::_Logger[$Name] -or $Force) { 
            [Logger]::_Logger[$Name] = [Log]::new($Name,[Logger]::Path).Start([Logger]::Append)
        }
        return [Logger]::_Logger[$Name]
    }

    static Setup([string] $Path) { [Logger]::Setup($Path,$true) }

    static Setup([string] $Path, [bool] $Append) {
        [Logger]::Path = $Path
        [Logger]::Append = $Append
    }
}

非常感谢mhu,我现在可以通过调用

在任何脚本文件中使用此类

[Logger]::Get().<Entry Type Method>() Get()要么打开为脚本创建的现有日志,要么创建一个新日志