【问题标题】:can a New-Module return a psobject?新模块可以返回一个 psobject 吗?
【发布时间】:2016-06-22 23:24:46
【问题描述】:

下面的这个模块返回一个空对象。有什么建议可以解决吗?

New-Module -ScriptBlock { 
    $resourcesDirectory="AA"
    .....
    $commonProperties = New-Object PSObject -Property @{
        ResourcesDirectory = $resourcesDirectory
    }

    return $commonProperties 
} -name GetXXX

【问题讨论】:

  • 一切都是psobject

标签: powershell powershell-module


【解决方案1】:

PetSerAl 致敬以寻求帮助。

New-Module 默认返回新创建的模块,作为[System.Management.Automation.PSModuleInfo] 实例。

“返回一个空对象”我认为你的意思是你的意图是让你的模块导出$commonProperties变量(其中恰好包含一个 [pscustomobject] 实例,但这是偶然的),但您的代码未能这样做。

原因是在没有Export-ModuleMember 调用的情况下,变量别名——不像函数——是不会自动从模块中导出

注意事项

  • 如果存在一个或多个Export-ModuleMember 调用导出指定的成员(不会自动导出任何内容)。

    李>
  • Export-ModuleMember 调用最好放在模块定义的底部,因为它们必须的定义之后要自己导出的元素。

  • 如果您想将导入当前会话的导出成员集限制为模块函数子集,可以使用New-Module's -Function参数。

    • 如果该模块仅在当前会话中使用,则将New-Module -FunctionExport-ModuleMember 结合使用是没有意义的;另请注意,使用-Function 会阻止将非函数成员导入当前会话。
    • 结合默认导出行为,New-Module -Function 有效 提供了在脚本块内使用带有函数名称的显式 Export-ModuleMember 调用的替代方法,但了解这两种机制很重要不同。

要导出变量$commonProperties,您需要调用Export-ModuleMember -Variable commonProperties(注意变量名中必须缺少前缀$):

$newModule = New-Module -ScriptBlock { 
    $resourcesDirectory="AA"
    $commonProperties = New-Object PSObject -Property @{
        ResourcesDirectory = $resourcesDirectory
    }

    # You must explicitly export variable $commonProperties.
    # Note that `Export-ModuleMember` must generally come *after* the 
    # definition of the variable, and that the variable name 
    # must not be $-prefixed.
    Export-ModuleMember -Variable commonProperties

    # (No need to `return` anything from the script block.
    #  Any output will be ignored.)
} -name GetXXX

鉴于New-Module 不仅会创建一个新模块,而且会自动导入它,$commonProperties 现在可以在当前会话中使用。


旁注

通过添加开关-ReturnResult,您可以告诉New-Module返回您的脚本块的输出,而不是新创建的模块对象(但模块仍被导入到当前会话中)。

由于return $commonProperties 语句,应用于将返回变量$commonProperties 的代码,但如上所述,您的脚本块不会导出 任何成员,因此当前会话不会看到$commonProperties 变量


或者,切换 -AsCustomObject 告诉 New-Module 返回一个 [pscustomobject] 实例,其成员是导出的成员
请注意,正常的导出规则适用,并且模块仍在幕后创建,尽管它没有导入

应用于您的(更正后的)代码,并添加了导出函数Foo

$newObj = New-Module -ScriptBlock { 
    $resourcesDirectory="AA"
    $commonProperties = New-Object PSObject -Property @{
        ResourcesDirectory = $resourcesDirectory
    }
    function Foo { "I'm here." }
    Export-ModuleMember -Variable commonProperties -Function Foo
} -AsCustomObject

$newObj 现在包含一个名为 commonProperties 的属性,该属性引用来自新(隐藏)模块脚本块的 $commonProperty 变量。

注意:Get-Member 误导性地将此属性的类型报告为NoteProperty,暗示 static 值,而导出的函数可能会改变底层变量的值(尽管这让我觉得这是一个奇特的案例) .真正的类型是[System.Management.Automation.PSVariableProperty],正如$newObj.psobject.properties['commonProperties'].GetType().FullName 所揭示的那样,而真正的NoteProperty 成员具有[System.Management.Automation.PSNoteProperty] 类型。

类似地,导出的函数 Foo 表面为ScriptMethod 类型的成员(方法),它在新(隐藏)模块的上下文中运行并看到其 em> 变量。
(顺便说一句:$newObj.Foo.Script.Module 可用于访问隐藏模块。)

相比之下,导出的别名看似忽略

警告:不要以相同名称导出不同类型的成员(例如,不要定义同名的函数和变量),因为只有其中一个可以访问。

【讨论】:

  • +1 这个答案,因为它突出了我的回复,你没有导出任何东西。要么显式导出,要么使用 -function 参数。
  • @ConradB:谢谢。我只是大幅改写了(希望)使它更有用的答案;感谢-Function 参数提示,我已将其合并到答案中。
  • 或者,开关 -AsCustomObject 告诉 New-Module 不要实际创建和导入模块 是的,模块未导入,但仍需要创建。 (New-Module { function f { } } -AsCustomObject).f.Script.Module
  • 另请注意,导出的变量不仅仅是NoteProperty$co=New-Module { function Increment { (++$script:Value) } $Value=0; Export-ModuleMember -Function Increment -Variable Value } -AsCustomObject; $co.PSObject.Properties['Value'].GetType().FullName。它们没有自己的值,但链接回导出的变量:$co.Value=123; $co.Increment(); $co.Value
  • @PetSerAl:再次感谢,出色的背景信息 - 答案再次更新。
猜你喜欢
  • 2018-09-18
  • 1970-01-01
  • 2018-10-01
  • 1970-01-01
  • 2011-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
相关资源
最近更新 更多