简体   繁体   中英

can a New-Module return a psobject?

This module below returns a empty object . Any suggestions to fix it ?

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

    return $commonProperties 
} -name GetXXX

Tip of the hat to PetSerAl for his help.

New-Module by default returns the newly created module, as a [System.Management.Automation.PSModuleInfo] instance.

By "returns an empty object" I presume you mean that your intent is to have your module export the $commonProperties variable (which happens to contain a [pscustomobject] instance, but that is incidental), yet your code failed to do so.

The reason is that in the absence of Export-ModuleMember calls, variables and aliases - unlike functions - are not automatically exported from a module .

Caveats :

  • If one or more Export-ModuleMember calls are present, only the specified members are exported (nothing is exported automatically).

  • Export-ModuleMember calls are best placed at the bottom of your module definition, because they must come after the definitions of the elements to export themselves.

  • If you want to limit the set of exported members that are imported into the current session to a subset of the module's functions , you can use New-Module 's -Function parameter.

    • If the module is used in the current session only, there's no point in combining New-Module -Function with Export-ModuleMember ; also note that using -Function will prevent non-function members from being imported into the current session.
    • Combined with the default exporting behavior, New-Module -Function effectively provides an alternative to using an explicit Export-ModuleMember call with the function names inside the script block, though it's important to understand that the two mechanisms differ.

To export variable $commonProperties , you need to call Export-ModuleMember -Variable commonProperties (note the required absence of prefix $ from the variable name):

$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

Given that New-Module not only creates a new module but automatically imports it, $commonProperties is now available in the current session.


Side notes :

By adding switch -ReturnResult , you can tell New-Module to return your script block's output rather than the newly created module object (but the module is still imported into the current session).

Applied to your code that would return the value of variable $commonProperties , due to the return $commonProperties statement, but, as stated, your script block does not export any members, so the current session wouldn't see the $commonProperties variable .


Alternatively, switch -AsCustomObject tells New-Module to return a [pscustomobject] instance whose members are the exported members .
Note that normal export rules apply, and that a module is still being created behind the scenes, although it isn't imported .

Applied to your (corrected) code, with exported function Foo added:

$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 now contains a property named commonProperties that references the $commonProperty variable from the new (hidden) module's script block.

Note: Get-Member misleadingly reports this property's type as NoteProperty , suggesting a static value, whereas an exported function can potentially alter the value of the underlying variable (although that strikes me as an exotic case). The true type is [System.Management.Automation.PSVariableProperty] , as $newObj.psobject.properties['commonProperties'].GetType().FullName reveals, whereas a true NoteProperty member has type [System.Management.Automation.PSNoteProperty] .

Similarly, the exported function Foo surfaces as a ScriptMethod -type member (method) that operates in the context of the new (hidden) module and sees its variables.
(As an aside: $newObj.Foo.Script.Module can be used to gain access to the hidden module.)

By contrast, exported aliases are seemingly ignored .

Caveat : Do not export members of different types by the same name (eg, do not define a function and variable of the same name), as only one of them will be accessible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM