Powershell 模块是否可以调用其导入程序范围内的函数?



powershell模块是否可以调用其导入程序范围内的函数?

例如,假设我有module.psm1和script.ps1。在script.ps1中,我导入module.psm1,并定义一个名为Execute Payload的函数。module.psm1中的代码有什么方法可以调用Execute Payload吗?

如果我正确理解您要做的事情,有两种常用的方法可以将自定义函数加载到主脚本中。我会给你举几个例子,因为我不确定是否有这样的最佳实践。

在所有给定的示例中,正在执行的脚本将始终为main.ps1

  • 示例1:所有函数都存储在一个文件中

文件夹结构

../path/to/script/main.ps1
../path/to/script/Functions/functions.ps1

Functions.ps1

function myCustomFunction1 {
....
}
function myCustomFunction2 {
....
}
function myCustomFunction3 {
....
}

main.ps1

在代码的第一行,你可以添加这样的内容:

$ErrorActionPreference = 'Stop'
# Option 1: Using Import-Module.
try
{
Import-Module "$PSScriptRootFunctionsfunctions.ps1"
}
catch
{
"Failed to load dependency Functions.`nError: $_"
}
# Option 2: Dot Sourcing
try
{
. "$PSScriptRootFunctionsfunctions.ps1"
}
catch
{
"Failed to load dependency Functions.`nError: $_"
}

注意:这两个选项都将加载ALL函数

  • 示例2:许多函数存储在不同的文件中。当你有很多复杂和/或冗长的函数时,就会用到这个

文件夹结构

../path/to/script/main.ps1
../path/to/script/Functions/myCustomFunction1.ps1
../path/to/script/Functions/myCustomFunction2.ps1
../path/to/script/Functions/myCustomFunction3.ps1

myCustomFunction1.ps1

function myCustomFunction1 {
....
}

myCustomFunction2.ps1

function myCustomFunction2 {
....
}

myCustomFunction3.ps1

function myCustomFunction3 {
....
}

main.ps1

在代码的第一行,你可以添加这样的内容:

$ErrorActionPreference = 'Stop'
# Option 1: Using Import-Module.
try
{
Get-ChildItem "$PSScriptRootFunctions*.ps1" | Import-Module
}
catch
{
"Failed to load dependency Functions.`nError: $_"
}
# Option 2: Dot Sourcing
try
{
Get-ChildItem "$PSScriptRootFunctions*.ps1" | ForEach-Object {
. $_.FullName
}
}
catch
{
"Failed to load dependency Functions.`nError: $_"
}

在模块的(高级(函数中,可以使用带参数$PSCmdlet.SessionState$PSCmdlet.InvokeCommand.InvokeScript()和从字符串创建的脚本块来执行调用方作用域中的任意代码。

这项技术很感激地改编自GitHub上的这条评论

为了简洁起见,以下代码演示了使用New-Module创建的动态模块的技术,但它同样适用于常规的持久化模块:

# The function to call from the module.
function Execute-Payload {
"Inside Execute-Payload in the script's scope."
}
# Create (and implicitly import) a dynamic module.
$null = New-Module {
# Define the advanced module function that calls `Execute-Payload`
# in its caller's scope.
function Invoke-Something {
[CmdletBinding()]
param()
$PSCmdlet.InvokeCommand.InvokeScript(
$PSCmdlet.SessionState,
# Pass a *string* with arbitrary code to execute in the caller's scope to 
# [scriptblock]::Create().
# !! It is imperative that [scriptblock]::Create() be used, with
# !! a *string*, as it creates an *unbound* script block that then 
# !! runs in the specified session. 
# !! If needed, use string expansion to "bake" module-local variable 
# !! values into the string, or pass parameters as additional arguments.
# !! However, if a script block is passed *by the caller*,
# !! bound to *its* context, it *can* be used as-is.
[scriptblock]::Create(' Execute-Payload ')
)
}
}
# Now invoke the function defined in the module.
Invoke-Something

上面的输出Inside Execute-Payload in the script's scope.,证明脚本的函数被调用了。

相关内容

最新更新