powershell - 有没有办法让模块在首次运行时创建其所需的程序集?
问题描述
我正在尝试编写一个依赖于小型程序集的 PowerShell 模块。程序集是从 C# 文件 ( add-type -typeDefinition (get-content -raw xyz.cs) -outputAssembly xyz.dll -outputType library
) 创建的。因为模块需要这个程序集,所以我必须在安装模块时手动创建程序集。我现在想知道是否可以让 PowerShelladd-type ...
在首次使用时自动执行此步骤(或任何其他模块初始化步骤)
解决方案
笔记:
正如Mathias R. Jessen所指出的,没有必要将辅助程序集写入磁盘-在内存中创建它就足以满足您的用例(省略
-OutputType
和-OutputAssembly
参数,并跳过Add-Type -LiteralPath
下面代码中的调用)。- 这足够的原因是用于在函数中声明参数的类型的存在不是在定义(和导出)函数时强制执行,而是在调用它时(或调用它的帮助或它的名称被传递给
Get-Command -Syntax
)。
- 这足够的原因是用于在函数中声明参数的类型的存在不是在定义(和导出)函数时强制执行,而是在调用它时(或调用它的帮助或它的名称被传递给
但是,您可能仍希望使用基于磁盘的方法,如下所示,以免在您第一次导入模块时每台机器仅编译一次而导致性能损失。
- 还可以考虑实现版本控制机制,以便需要更新类型定义的模块更新在需要时重新创建帮助程序集。
下面的概念证明使用了一个独立的脚本./foo.psm1
模块(foo.dll
Add-Type
程序集定义了 sample 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.
推荐阅读
- python - 如何使链接出现在 django 的 base.html 中
- php - 如何获取xml子参数
- php - 如何在 DOM Pdf 中使用 Bootstrap?
- ruby-on-rails - 在构建一个新的本地目录以在本地存放应用程序之后,有没有人遇到过 Heroku 上的新部署崩溃的经历?
- c++ - 我可以像 C# 的 Action 一样使用 C++ 函数指针吗?
- amazon-web-services - AWS IOT 政策文件
- amazon-web-services - 用于静态网站托管的 S3 存储桶端点
- python - PyQt5 window.close() 不会关闭窗口,但 window.open() 工作正常
- spring - 具有类级别 url 注释的性能影响
- c# - 在屏幕共享程序中使用哈希存储图像缓冲区的内存管理