Powershell模块初始化
加载模块时,PowerShell是否调用任何初始化代码 我正在寻找Perl BEGIN块或构造函数之类的东西 NEW-MODULE和IMPORT-MODULE都将返回PSCustomObject。我试图将自定义对象封装在模块中,以避免脚本中的冗长代码。在开放代码中测试良好的一种方法是:Powershell模块初始化,powershell,module,Powershell,Module,加载模块时,PowerShell是否调用任何初始化代码 我正在寻找Perl BEGIN块或构造函数之类的东西 NEW-MODULE和IMPORT-MODULE都将返回PSCustomObject。我试图将自定义对象封装在模块中,以避免脚本中的冗长代码。在开放代码中测试良好的一种方法是: $m = new-module -scriptblock { New-Object PSCustomObject | Add-Member NoteProperty -name person -valu
$m = new-module -scriptblock {
New-Object PSCustomObject |
Add-Member NoteProperty -name person -value Frodo -passthru |
Add-Member ScriptMethod Who { $this.person } -passthru |
Add-Member ScriptMethod Mod {
param($x)
$this.person = $x
} -passthru
} -ascustomobject -returnresult
理想情况下,我希望将此代码放到一个模块中,并使用如下内容:
$MyObj = Import-Module -Name ".\MyPackage" -AsCustomObject
并使MyObj成为与第一个代码段提供的相同的对象句柄
非常感谢您的建议。模块实际上应该输出cmdlet,而不是对象。模块应提供一组相关的cmdlet。有一种方法可以使用如下所示的
Import Modules
的-ArgumentList
参数将数据发送到模块中。例如,您可以使用该技术为cmdlet提供要连接的服务器名称。PowerCLI模块使用创建脚本作用域连接对象($script:connection
)的cmdlet以不同的方式处理此问题,如果存在类似以下内容的对象,则其他cmdlet将检查并重新使用该对象:
#test.psm1
$script:myvar = "hi"
function Show-MyVar {Write-Host $script:myvar}
function Set-MyVar ($Value) {$script:myvar = $Value}
#end test.psm1
不清楚是要在加载模块时运行初始化代码(如Perl的BEGIN块),还是要创建自定义类(这是“构造函数”所建议的) 模块中的初始化代码很简单。导入模块时,将执行模块中未嵌入函数的任何代码 PS本机不支持创建自定义类。请参阅:。您还可以编写C#、VBScript等并使用Add Type 导入模块不能用于模拟类,因为您只能有一个具有给定名称的模块实例-最多只能有一个单例类。(顺便说一句,导入模块确实有一个-passthru参数,这或多或少会使您的最后一行代码作为一个单例工作。您还必须将
export-module-variable*-function*
添加到您的模块代码中)您可以使用新模块来模拟类。例如,您可以将其封装在名为newmyclass
的函数中
顺便说一句,如果使用-ASCustomObject参数,则最终会得到一个不支持“this”的哈希表(换句话说,作为脚本块的哈希表值没有一种内置的方式来引用哈希表本身)。如果使用不带-AsCustomObject的新模块(并且可能使用工厂函数,例如new myclass),则可以使用
和$myModule$varInMyModule
模拟“this.varInMyModule”。然而,如果您使用Add Member创建一个PSCustomObject,那么脚本方法就可以访问$this,并且它的行为通常更像一个具有属性和方法的典型对象。使用模块,您可以导出固有属性和函数,并且不需要通过Add Member运行它们,也不需要做很多杂技。但是,请注意,如果您不想导出所有属性和方法,并且可以将属性初始化为初始值,那么在初始化过程中,如果不执行akward Acrobatic,就不能调用内部函数,这会出现一些问题
但我认为您真正想要做的是使用Powershell 5中现在可用的类(您发布时没有)。我提供了每种方法的示例。
Sysops在4个部分中对新类进行了详细介绍
这是powershell 5.0之前的老方法
# powershell 3.0 and above (I think)
$m = new-module -ascustomobject -scriptblock `
{
$person = "Frodo"
function Who
()
{return $this.person}
function Rename
($name)
{$this.person = $name}
Export-ModuleMember -Function * -Variable *
}
write-host "direct property access: $($m.person)"
write-host "method call: $($m.who())"
$m.Rename("Shelob")
write-host "change test: $($m.who())"
您还可以从模板复制多个对象,如下所示:
# powershell 3.0 and above (I think)
$template = `
{
$person = "Frodo"
function Who
()
{return $this.person}
function Rename
($name)
{$this.person = $name}
Export-ModuleMember -Function * -Variable *
}
$me = new-module -ascustomobject -scriptblock $template; $me.Rename("Shelob")
$you = new-module -ascustomobject -scriptblock $template
"Me: $($me.Who())"
"You: $($you.Who())"
在powershell 5中,您有实际的类(大部分)
#需要-版本5
班主任
{
隐藏的[字符串]$name#实际上不是私有的
[字符串]谁()
{返回$this.name}
[void]重命名([string]$name)
{$this.name=$name}
#尽管构造函数很奇怪,但您没有指定返回类型或显式返回值。
人员([String]$name)
{$this.name=$name}
您是否有文档链接确认“模块中未嵌入函数的任何代码都会在导入模块时执行”。我相信这是半真半假:用PowerShell编写的模块就是这样工作的,用C#编写的模块似乎没有办法做到这一点(除非您编辑CIL并添加.ModuleInit,例如使用Fody生成后处理程序,因为ModuleInit不符合公共语言规范)。
#requires -version 5
Class Person
{
hidden [String] $name #not actually private
[string] Who ()
{return $this.name}
[void] Rename ([string] $name)
{$this.name = $name}
# constructors are weird though, you don't specify return type OR explicitly return value.
Person ([String]$name)
{$this.name = $name}
<#
# The above constructor code is secretly converted to this
[Person] New ([string]$name) #note the added return type and renamed to New
{
$this.name = $name
return $this #note that we are returning ourself, you can exploit this to create chained constructors like [person]::New("gandalf").withWizardLevel("White") but I haven't done so here
}
#>
}
$me = [Person]::new("Shelob")
$you = [Person]::new("Frodo")
# $me|gm # Note that Name doesn't show here
# $me.name # But we can still access it...
# $me|gm -Force # Note that Name DOES show here
"`n"
"Me: $($me.who())"
"You: $($you.who())"
$you.Rename("Dinner")
"You after we meet: $($you.who())"