powershellmodule

New changes not importing when using Import-Module from an advanced function in PowerShell


Summary of problem: When I attempt to call Import-Module from a PowerShell advanced function, it is not importing the new changes. Maybe a caching issue?

What works so far:

  1. Importing the module by typing the full command in the terminal works great, but I want to automate this so I don't have to type in the full path each time I change to a new module.
Import-Module -Name 'G:\Development\POSH\dev\modules\JnTestModule\JnTestModule\JnTestModule.psd1' -Force -Verbose
  1. Copying my advanced function to an external file named testModule.ps1 and executing it directly from the module project root folder also works great.

Sample code in testModule.ps1

function Import-JnScriptModule
{
  <#
  .SYNOPSIS
    Quickly import my custom PowerShell script module for testing changes.

  .EXAMPLE
    Import-JnScriptModule
  #>
  [CmdletBinding()]
  [Alias('imp')]
  param()
  begin {}
  process
  {
    $modulesRootDirectory = "G:\Development\POSH\dev\modules"
    Write-Debug "modulesRootDirectory:$modulesRootDirectory"

    $currentDirectory = (Get-Location).Path
    Write-Debug "currentDirectory:$currentDirectory"

    Write-Verbose "Check if we are in the modules dev directory."
    if ($currentDirectory.StartsWith("$modulesRootDirectory"))
    {
      if(!$moduleName)
      {
        $moduleName = (Get-Item -Path $currentDirectory).BaseName
      }

      Write-Debug "moduleName:$moduleName"

      $manifestFileName = "$moduleName.psd1"
      Write-Debug "manifestFileName:$manifestFileName"

      $projectDirectory = Join-Path -Path $modulesRootDirectory -ChildPath $moduleName
      Write-Debug "projectDirectory:$projectDirectory"

      $moduleManifestFullPath = Join-Path -Path $projectDirectory -ChildPath $moduleName -AdditionalChildPath $manifestFileName
      Write-Debug "moduleManifestFullPath:$moduleManifestFullPath"

      if ((Test-Path -Path $moduleManifestFullPath) -eq $true)
      {
        Remove-Module -Name "$moduleName" -Force -ErrorAction SilentlyContinue
        Import-Module -Name "$moduleManifestFullPath" -Force -Verbose
      }
      else
      {
        Write-Verbose "Unable to find module manifest path at '$moduleManifestFullPath'."
      }
    }
    else
    {
      Write-Warning "Skipped import because not a module folder."
    }
  }
  end {}
}

Import-JnScriptModule

This way works, but then I need to include a copy of testModule.ps1 in each modules project folder and I won't be able to use the alias 'imp' to execute it. I also prefer to have the code in a central location if possible.

What I want to accomplish: Add the advanced function to a custom script module that I use to manage my modules, then use this to quickly import a custom script module in development.

I would like to be able to simply type alias 'imp' while in the module project directory for a fast import, test changes and quick iterations. See a couple examples below.

PS G:\Development\POSH\dev\modules\JnTestModule> imp 
PS G:\Development\POSH\dev\modules\JnTestModule2> imp

When I type 'imp' it appears to execute the function and import the module, but the latest changes are not imported. Not sure if this is a caching issue or not, but in my function, I make sure to remove the existing module from the session first before forcing another import. This is not working.

Does anyone know if there is a way to make this work?

I am also open to other suggestions or work arounds. Thanks!


Solution

  • Add the advanced function to a custom script module

    Your problem is that importing modules from a module scopes these imports to that module (i.e. makes them only visible only there), whereas in your case you want the module to be imported into the caller's scope (which is in the non-module scope domain ("session state") when calling from outside a module).[1]

    A simple workaround is to add -Global to your Import-Module calls (which, as the name suggests, imports the module globally, i.e. across all scope domains, which is also what happens by default when calling Import-Module from the non-module scope domain).


    [1] For more information about PowerShell scope domains ("session states"), see this answer.