Module Nesting

This topic contains 4 replies, has 2 voices, and was last updated by  Aurimas N. 3 weeks, 5 days ago.

  • Author
    Posts
  • #92045

    Aurimas N.
    Participant

    Hi,
    I would like to have multiple modules/scripts nested and imported with one module, the problem is that I want to keep the actual files across multiple directories:

    BuildTests[dir]
    |BuildTests.psd1
    |GenericTests[dir]
    ||GenericTests.psd1
    ||GenericTest1.ps1
    ||GenericTest2.ps1
    |SpecificTests[dir]
    ||SpecificTests.psd1
    ||SpecificTest1.ps1
    ||SpecificTest2.ps1

    I want to keep 1 function per .ps1 file.
    I have tried the following:
    in BuildTests.psd1 define NestedModules = @('.\GenericTests\GenericTests.psd1','.\SpecificTests\SpecificTests.psd1')
    in GenericTests.psd1 define ScriptsToProcess = @('GenericTest1.ps1','GenericTest2.ps1')
    accordingly configure SpecificTests.psd1

    Basically this works, however when checking get-module, I see all the functions from .ps1 files imported twice, checking further import-module with -verbose parameter, I can see that one time it is "loading module ...test1.ps1" and next line is "Dot-Sourcing the script file ....test1.ps1".
    I have tried different variations in .psd1 (changing from .ps1 to .psm1 and including them in nestedmodules), but I always seem to end up with duplicates imported or no functions imported at all.

  • #92048

    Don Jones
    Keymaster

    None of your files are explicitly loading or dot-sourcing these outside of what you've mentioned here? I ask because, just sitting on this end, the logic you're describing is a little tough for me to follow. It might be easier (for me) if you started with _what you want to happen_ rather than what you've done...?

    • #92050

      Aurimas N.
      Participant

      None of my files are loading nor dot sourcing anything.

      I would like multiple functions, each defined in its own .ps1 file across multiple folders, to be available in a single module.
      I would also prefer to maintain one manifest per folder and have all of those manifests included in a "root" manifest, if that is possible.

      or in other words:
      RootModule – includes nested modules from different folders.
      Each nested module includes .ps1 files in their respective folder.

  • #92053

    Don Jones
    Keymaster

    So... I suppose I'll start with how _I_ would do this.

    I would build all fo your functions as modules. .psm1 files, with .psd1 manifests, stored in folders as discrete, standalone modules. I wouldn't try using .ps1's – I'm not sure I see any advantage to doing so. Then, in my "parent" modules, I could simply specify all the ones I wanted at that one level.

    The nesting functionality wasn't really meant to support "sub-sub" multiple levels of nesting, and by combining modules and scripts, I feel you're making it unnecessarily complicated.

    Now, if the only way you want to live life is by having the "child" modules use a .ps1 for some reason, then I'd just have them dot-source their respective .ps1 files in the module code itself, rather than in a manifest. Although I still don't see the advantage of building a module that way, I suppose it's a free world ;).

    • #92060

      Aurimas N.
      Participant

      It looks like it's working just fine, what got me confused was the verbose output listing exporting/importing same function multiple times:

      PS D:\DevRepository\ParentModule> Import-Module .\ParentModule.psd1 -Verbose
      VERBOSE: Loading module from path 'D:\DevRepository\ParentModule\ParentModule.psd1'.
      VERBOSE: Loading module from path 'D:\DevRepository\ParentModule\Modules1\Modules1.psd1'.
      VERBOSE: Loading module from path 'D:\DevRepository\ParentModule\Modules1\TestCase1.ps1'.
      VERBOSE: Dot-sourcing the script file 'D:\DevRepository\ParentModule\Modules1\TestCase1.ps1'.
      VERBOSE: Exporting function 'test-case1'.
      VERBOSE: Importing function 'test-case1'.
      VERBOSE: Exporting function 'test-case1'.
      VERBOSE: Importing function 'test-case1'.

      And then checking the module ExportedFunctions property:

      PS D:\DevRepository\ParentModule> Get-Module ParentModule | select ExportedFunctions
      
      ExportedFunctions
      -----------------
      {[test-case1, test-case1]}

      Which actually lists key/value pairs:

      PS D:\DevRepository\ParentModule> (Get-Module ParentModule).ExportedFunctions
      
      Key        Value
      ---        -----
      test-case1 test-case1

      Regarding .ps1 vs .psm1 it just felt unnatural to have a .psm1 with just a single function, but otherwise I really have no preference, so might as well rename those to psm1.

      Thanks.

You must be logged in to reply to this topic.