如果我有以下内容(简化的设置)
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。
对于基于函数的嵌套调用有效,但不适用于对类的调用
答案 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()要么打开为脚本创建的现有日志,要么创建一个新日志