Powershell模块初始化

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

加载模块时,PowerShell是否调用任何初始化代码

我正在寻找Perl BEGIN块或构造函数之类的东西

NEW-MODULE和IMPORT-MODULE都将返回PSCustomObject。我试图将自定义对象封装在模块中,以避免脚本中的冗长代码。在开放代码中测试良好的一种方法是:

$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())"