有没有办法让模块在第一个 运行 时创建其所需的程序集?
Is there a way for a module to create its required assemblies when it is first run?
我正在尝试编写一个依赖于小型程序集的 PowerShell 模块。该程序集是从 C# 文件 (add-type -typeDefinition (get-content -raw xyz.cs) -outputAssembly xyz.dll -outputType library
) 创建的。因为模块需要这个程序集,所以我必须在安装模块时手动创建程序集。我现在想知道是否可以让 PowerShell 在首次使用时自动执行此 add-type ...
步骤(或任何其他模块初始化步骤)
注:
正如 Mathias R. Jessen 指出的那样,没有严格的必要将辅助程序集 写入磁盘 - 在 中创建它memory 足以满足您的用例(省略 -OutputType
和 -OutputAssembly
参数,并跳过下面代码中的 Add-Type -LiteralPath
调用)。
- 这就足够了,因为在函数被定义(和导出)时,用于在函数中声明参数的类型的存在并没有被强制执行,但是而不是在 调用 时(或调用其帮助或将其名称传递给
Get-Command -Syntax
)。
但是,您可能仍想使用基于磁盘的方法,如下所示,这样会导致编译仅 一次 的性能损失每台机器,第一次导入模块时。
- 同时考虑实施版本控制机制,以便需要更新类型定义的模块更新在需要时重新创建助手程序集。
以下概念验证使用独立脚本模块 (./foo.psm1
),其顶层代码测试是否存在与模块相同位置的辅助程序集 foo.dll
,并且,如果找不到,则使用 Add-Type
.
创建它
程序集定义了示例类型[demo.Foo]
,模块导出的Use-Foo
模块函数将其用作参数类型。
在实际使用中,对于基于 目录 的模块,您只需指向模块清单(*.psd1
文件的)RootModule
条目相当于 foo.psm1
文件。
# Create demo module ./foo.psm1
@'
# Deactivate this to silence the verbose messages.
$VerbosePreference = 'Continue'
$dllPath = "$PSScriptRoot/foo.dll"
if (-not (Test-Path $dllPath)) {
Write-Verbose "Creating assembly $dllPath..."
Add-Type -ErrorAction Stop -OutputType Library -OutputAssembly $dllPath '
namespace demo {
public class Foo {
public string Bar { get { return "I am a Foo instance."; } }
}
}
'
}
else {
Write-Verbose "Using preexisting $dllPath assembly."
}
Write-Verbose "Loading assembly $dllPath..."
Add-Type -ErrorAction Stop -LiteralPath $dllPath
# Define the function to be exported, whose parameter
# uses the type defined by the helper assembly.
function Use-Foo {
param(
[demo.Foo] $foo
)
$foo.Bar
}
'@ > ./foo.psm1
# Import the module, at which point the top-level code runs,
# which either creates the helper assembly or loads a previously
# created copy.
Import-Module -Force -Verbose ./foo.psm1
Write-Verbose -vb 'Calling Use-Foo...'
Use-Foo ([demo.Foo]::new())
运行 上面第一次得到如下结果,证明程序集是按需创建,加载,并且使用程序集定义的类型作为导出的参数类型Use-Foo
函数成功:
VERBOSE: Loading module from path '/Users/jdoe/demo/foo.psm1'.
VERBOSE: Creating assembly /Users/jdoe/demo/foo.dll...
VERBOSE: Loading assembly /Users/jdoe/demo/foo.dll...
VERBOSE: Exporting function 'Use-Foo'.
VERBOSE: Importing function 'Use-Foo'.
VERBOSE: Calling Use-Foo...
I am a Foo instance.
我正在尝试编写一个依赖于小型程序集的 PowerShell 模块。该程序集是从 C# 文件 (add-type -typeDefinition (get-content -raw xyz.cs) -outputAssembly xyz.dll -outputType library
) 创建的。因为模块需要这个程序集,所以我必须在安装模块时手动创建程序集。我现在想知道是否可以让 PowerShell 在首次使用时自动执行此 add-type ...
步骤(或任何其他模块初始化步骤)
注:
正如 Mathias R. Jessen 指出的那样,没有严格的必要将辅助程序集 写入磁盘 - 在 中创建它memory 足以满足您的用例(省略
-OutputType
和-OutputAssembly
参数,并跳过下面代码中的Add-Type -LiteralPath
调用)。- 这就足够了,因为在函数被定义(和导出)时,用于在函数中声明参数的类型的存在并没有被强制执行,但是而不是在 调用 时(或调用其帮助或将其名称传递给
Get-Command -Syntax
)。
- 这就足够了,因为在函数被定义(和导出)时,用于在函数中声明参数的类型的存在并没有被强制执行,但是而不是在 调用 时(或调用其帮助或将其名称传递给
但是,您可能仍想使用基于磁盘的方法,如下所示,这样会导致编译仅 一次 的性能损失每台机器,第一次导入模块时。
- 同时考虑实施版本控制机制,以便需要更新类型定义的模块更新在需要时重新创建助手程序集。
以下概念验证使用独立脚本模块 (./foo.psm1
),其顶层代码测试是否存在与模块相同位置的辅助程序集 foo.dll
,并且,如果找不到,则使用 Add-Type
.
程序集定义了示例类型[demo.Foo]
,模块导出的Use-Foo
模块函数将其用作参数类型。
在实际使用中,对于基于 目录 的模块,您只需指向模块清单(*.psd1
文件的)RootModule
条目相当于 foo.psm1
文件。
# Create demo module ./foo.psm1
@'
# Deactivate this to silence the verbose messages.
$VerbosePreference = 'Continue'
$dllPath = "$PSScriptRoot/foo.dll"
if (-not (Test-Path $dllPath)) {
Write-Verbose "Creating assembly $dllPath..."
Add-Type -ErrorAction Stop -OutputType Library -OutputAssembly $dllPath '
namespace demo {
public class Foo {
public string Bar { get { return "I am a Foo instance."; } }
}
}
'
}
else {
Write-Verbose "Using preexisting $dllPath assembly."
}
Write-Verbose "Loading assembly $dllPath..."
Add-Type -ErrorAction Stop -LiteralPath $dllPath
# Define the function to be exported, whose parameter
# uses the type defined by the helper assembly.
function Use-Foo {
param(
[demo.Foo] $foo
)
$foo.Bar
}
'@ > ./foo.psm1
# Import the module, at which point the top-level code runs,
# which either creates the helper assembly or loads a previously
# created copy.
Import-Module -Force -Verbose ./foo.psm1
Write-Verbose -vb 'Calling Use-Foo...'
Use-Foo ([demo.Foo]::new())
运行 上面第一次得到如下结果,证明程序集是按需创建,加载,并且使用程序集定义的类型作为导出的参数类型Use-Foo
函数成功:
VERBOSE: Loading module from path '/Users/jdoe/demo/foo.psm1'.
VERBOSE: Creating assembly /Users/jdoe/demo/foo.dll...
VERBOSE: Loading assembly /Users/jdoe/demo/foo.dll...
VERBOSE: Exporting function 'Use-Foo'.
VERBOSE: Importing function 'Use-Foo'.
VERBOSE: Calling Use-Foo...
I am a Foo instance.