Eri*_*ris 5 powershell powershell-2.0 powershell-3.0
给定一个 ps1 文件作为模块的一部分,代码如下:
function Get-Greeting {
'Hello {0}' -f $Env:Username
}
Export-ModuleMember -Function:Get-Greeting
Run Code Online (Sandbox Code Playgroud)
当作为模块的一部分加载时,一切都很好。如果我对脚本进行点源,我会得到
Export-ModuleMember : The Export-ModuleMember cmdlet can only be called from inside a module.
Run Code Online (Sandbox Code Playgroud)
我知道我可以在 Export-ModuleMember 上添加 -ErrorAction:Ignore,但这不是重点。我想让脚本以不同的方式运行,无论它是导入的还是点源的。
在版本 2 中,人们可能可以围绕 编写一个 hack $PSScriptRoot,但这只是一个 hack,并且在版本 3 中不起作用,在版本 3 中它们“固定”$PSScriptRoot为永不为空。我尝试查看 中的各种项目$MyInvocation,但要么我错过了一些东西,要么它没有任何有用的东西。
我还尝试Get-Variable在模块内部和外部运行,但再次发现没有差异。
Import-Module当运行 as vs时我错过了什么不同的地方. myscript.ps1?
看来我找到了这个问题的答案。我遗漏了一些东西$MyInvocation,因为我在错误的范围内寻找。给定以下文件:
# .\moduleDetection\moduleDetection.ps1
$ErrorActionPreference = 'SilentlyContinue';
'=== Parent Invocation.MyCommand: [{0}]' -f (Get-Variable -Name:MyInvocation -Scope:1 -ValueOnly | Select -Expand MyCommand) | Out-Host;
Run Code Online (Sandbox Code Playgroud)
。
# .\moduleDotSource\moduleDotSource.psm1
. "$PSScriptRoot\..\moduleDetection\moduleDetection.ps1"
Run Code Online (Sandbox Code Playgroud)
。
# .\module-test.ps1
$Error.Clear()
Write-Host "Powershell Version 3:"
Write-Host "Powershell -Command Import-Module (direct)"
powershell -nologo -noprofile -Command { Import-Module .\moduledetection }
Write-Host "Powershell -Command Import-Module (dot-source)"
powershell -nologo -noprofile -Command { Import-Module .\moduleDotSource }
Write-Host "Powershell -File ...moduledetection.ps1"
powershell -nologo -noprofile -File .\moduledetection\moduleDetection.ps1
Write-Host "Powershell Dot-Source"
powershell -nologo -noprofile -Command { . .\moduledetection\moduleDetection.ps1 }
Write-Host ""
Write-Host "Powershell Version 2:"
Write-Host "Powershell -Version 2 -Command Import-Module"
powershell -version 2.0 -nologo -noprofile -Command { Import-Module .\moduledetection }
Write-Host "Powershell -Version 2 -Command Import-Module (dot-source)"
powershell -version 2.0 -nologo -noprofile -Command { Import-Module .\moduleDotSource }
Write-Host "Powershell -Version 2 -File ...moduledetection.ps1"
powershell -version 2.0 -nologo -noprofile -File .\moduledetection\moduleDetection.ps1
Write-Host "Powershell -Version 2 Dot-Source"
powershell -version 2.0 -nologo -noprofile -Command { . .\moduledetection\moduleDetection.ps1 }
Run Code Online (Sandbox Code Playgroud)
最后,使用正确的名称从原始 ps1 到 psm1 建立符号链接以作为直接模块加载。
cmd /c mklink .\moduledetection\moduleDetection.ps1 .\moduledetection\moduleDetection.psm1
Run Code Online (Sandbox Code Playgroud)
输出显示父作用域具有密钥。
输出:
Powershell Version 3:
Powershell -Command Import-Module (direct)
=== Parent Invocation.MyCommand: [ Import-Module .\moduledetection ]
Powershell -Command Import-Module (dot-source)
=== Parent Invocation.MyCommand: [ Import-Module .\moduleDotSource ]
Powershell -File ...moduledetection.ps1
Powershell Dot-Source
Powershell Version 2:
Powershell -Version 2 -Command Import-Module
=== Parent Invocation.MyCommand: [ Import-Module .\moduledetection ]
Powershell -Version 2 -Command Import-Module (dot-source)
=== Parent Invocation.MyCommand: [ Import-Module .\moduleDotSource ]
Powershell -Version 2 -File ...moduledetection.ps1
Powershell -Version 2 Dot-Source
Run Code Online (Sandbox Code Playgroud)
正如我们从显示的输出(在 Server 2008 R2 上运行)中看到的,父作用域$MyInvocation.MyCommand包含导入模块语句。我还没有测试它,但我从中推断,如果它是通过链式点源的多重间接,我们可以继续获取父作用域,直到我们得到 Null 或导入模块。
现在我们知道如何检测我们是否在模块中,并且通过其他资源也可以了解我们是否是点源、直接执行和/或通过模块加载。
| 归档时间: |
|
| 查看次数: |
3012 次 |
| 最近记录: |