Как получить имя файла скрипта, из которого вызывается класс, когда он вложен в вызов точечного источника - PullRequest
0 голосов
/ 03 июля 2019

Если у меня есть следующее (упрощенная установка)

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 (не то, чтобы переместить источник точек в один файл утилиты вэтот пример имеет значение)

Наконец, я использую Show-Object из модуля PowerShellCookbook.

Кажется странным, что он работает для вложенного вызова на основе функции, но не для вызова ккласс

Ответы [ 2 ]

2 голосов
/ 03 июля 2019

Вы можете использовать стек для определения вызывающей стороны:

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
    }
}
0 голосов
/ 13 июля 2019

мху заслуживает полной оценки и официальной галочки ответа за то, что дал мне ответ.Но я решил опубликовать свои фиксированные классы с внедренным поведением для всех, кому нужно делать то, что мне нужно,

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 () либо открывает существующий журнал, созданный для сценарияили создает новый журнал

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...