每次执行脚本时重新加载PowerShell模块

每次执行脚本时重新加载PowerShell模块,powershell,module,reload,Powershell,Module,Reload,我在PowerShell模块文件中有一个类。(A.psm1) 我还有一个使用该类的简单脚本 Using module C:\temp\A.psm1 $a = [A]::new() $a.printString() # prints 111 但是如果我从类中更改方法,例如,如图所示(在222上替换111) 如果我重新启动脚本,它仍然会打印111。只有重新启动PowerShell控制台,它才会打印新值。 如果我只在控制台中工作,我可以使用导入模块-强制执行命令。但它在脚本中不起作用 那么,有没

我在PowerShell模块文件中有一个类。(
A.psm1

我还有一个使用该类的简单脚本

Using module C:\temp\A.psm1

$a = [A]::new()
$a.printString()  # prints 111
但是如果我从类中更改方法,例如,如图所示(在
222
上替换
111

如果我重新启动脚本,它仍然会打印
111
。只有重新启动PowerShell控制台,它才会打印新值。 如果我只在控制台中工作,我可以使用
导入模块-强制执行
命令。但它在脚本中不起作用


那么,有没有一种方法可以在每次启动脚本时重新加载PowerShell模块,而无需重新启动控制台本身?

据我所知,不幸的是,没有好的解决方案(从PowerShell 7.2开始):使用模块的
语句-也是从模块加载
es的先决条件-与强制重新加载模块的's
-Force
开关没有等效项

解决方法

# (Force-re)load the module and get a reference to the module.
# This does NOT give you access to the classes defined in the module.
$module = Import-Module C:\temp\A.psm1 -PassThru -Force

# Use the module reference to execute code *in the module's* context,
# where the class *is* defined, so you can obtain a reference to the
# [A] class (type) this way:
$classA = & $module { [A] }

$classA::new().printString()
  • 如您所见,这需要修改源代码

  • 如果将Visual Studio代码与PowerShell扩展一起使用,则可以避免此问题,如中所示


    • 这种不幸的行为是一种错误,目前还没有真正的好的解决方案

      根本原因有点复杂(行为持续5年以上的部分原因),但基本上是以下三方面的冲突:

      • PowerShell中的模块生命周期管理(模块应可重新加载)
      • .NET中的类型定义生命周期管理(在进程的生命周期内,类型永远不能“未定义”)
      • 使用module
的方式提供了自定义类型的解析时间解析——简单地说,这不是一个特别成熟的特性
虽然不存在好的解决方案,但VSCode PowerShell扩展有一个配置选项,因此不存在问题:

设置后,可以使用以下工作流进行测试/调试:

  • 在编辑器中打开脚本
  • 通过调试器运行它(
    Shift+Ctrl+D
    ->
    runanddebug
  • 观察
    printString()
    打印
    111
  • 对模块文件进行更改,然后保存
  • 再次通过调试器运行脚本
  • 观察
    printString()
    现在打印新值

  • 谢谢VS代码中的变通方法适合我的需要@非常高兴听到您的消息,不客气!FWIW这也是我用类开发模块的方法:-)我明白了:-)这很方便。
    [void] printString() {
         write-host 222
    }
    
    # (Force-re)load the module and get a reference to the module.
    # This does NOT give you access to the classes defined in the module.
    $module = Import-Module C:\temp\A.psm1 -PassThru -Force
    
    # Use the module reference to execute code *in the module's* context,
    # where the class *is* defined, so you can obtain a reference to the
    # [A] class (type) this way:
    $classA = & $module { [A] }
    
    $classA::new().printString()
    
    {
      "powershell.debugging.createTemporaryIntegratedConsole": true
    }