PowerShell:模块、它们的位置和重新加载

标签 powershell powershell-2.0 powershell-module

我有一个非常简单的 PS 脚本,它指的是一堆自写模块(psm1)。当我从 PowerShell ISE 运行我的脚本时,我经常把我的头发拉出来,因为我的模块的最新版本没有被执行(但是一些过时的-somewhere-stored-in-memory-version)。

我有 google-d 和 google-d,并且阅读并尝试过,现在是我非常感谢了解到底发生了什么的时候,而不是一直在解决这些问题。

一些示例代码:

(该脚本将配置将在我们的机器中服务的 PC,设置共享,创建本地用户,配置 NIC,诸如此类)

我首先将模块的位置添加到模块路径中,如下所示:

# Make sure .\Modules is part of the PSModulePath environment variable
$currentPSModulePath = [Environment]::GetEnvironmentVariable("PSModulePath", "Machine")
If (-Not ($currentPSModulePath -Like '*.\Modules*'))
{
    [Environment]::SetEnvironmentVariable("PSModulePath", $currentPSModulePath + ";.\Modules", "Machine")
}
Write-Host ("Environment variable for PSModulePath = {0}" -f [Environment]::GetEnvironmentVariable("PSModulePath", "Machine"))

然后,我加载所需的模块:
### Import Modules
Import-Module -DisableNameChecking ConfigureSystemPC
Import-Module -DisableNameChecking ConfigureChipPC
Import-Module -DisableNameChecking ConfigureEngravePC
Import-Module -DisableNameChecking ConfigureCInkPC
Import-Module -DisableNameChecking ConfigureIPPC
Import-Module -DisableNameChecking ConfigureNPPC

最后,我问用户应该配置哪台 PC:
### Start configuring new PC ###

Write-Host "`nChoose the PC type form the options below:`n"
Write-Host "1. System PC"
Write-Host "2. Chip PC"
Write-Host "3. Engrave PC"
Write-Host "4. CInkjet PC"
Write-Host "5. IP PC"
Write-Host "6. NP PC"
Write-Host "7. Output PC"

$pcType = Read-Host "Please enter the PC type and press [enter]"
Write-Host ("You choose option: {0}" -f $pcType)

switch ($pcType)
{
    1 { Configure-SystemPC }
    2 { Configure-ChipPC }
    3 { Configure-EngravePC }
    4 { Configure-CInkPC }
    5 { Configure-IPPC }
    6 { Configure-NPPC }
    7 { Configure-OutputPC }
}

当我更改配置模块中的某些内容时,问题就出现了。当我简单地添加(例如)Write-Host "bla bla" ,按保存按钮,再次调试我的主脚本(如上所示的脚本),PowerShell 将运行 模块的版本。

除非我通过以下任一方式重新加载模块:
  • rmo Configure-EngravePC后跟 ipmo Configure-EngravePC
  • ipmo Configure-EngravePC -Force

  • 我的模块的完全相同的“旧”版本将被执行。

    谁能指出我通常如何处理这个问题?
    为什么,为什么,为什么,当我通过调试器运行我的脚本时,我什至必须重新加载模块?为什么它会“存储”在不同 session 中运行的模块?难道我做错了什么?

    非常感谢,我希望有人能详细说明这一点,我经常卡住..

    我非常喜欢有正确解释的答案(或引用 好的 关于此主题的文档)

    最佳答案

    您需要重新启动 ISE,因为它保留单个控制台 AFAIK。

    现在,为了在不重新启动的情况下执行此操作,您要么必须创建新的 ISE 运行空间(文件>新 PowerShell 选项卡),要么放弃 ISE(推荐,因为它 sux)并使用正常的东西,例如 Cmder 并输入 ISE 仅用于广泛的调试或实现某种形式的自动重载。

    糟糕的解决方案是替换 prompt输入 ISE 时的功能(或将其添加到您的个人资料中):

    rename-item Function:prompt Function:old_prompt -ErrorAction ignore
    function global:prompt() {
        import-module -force Configure-EngravePC
        Function:old_prompt
    }
    

    这将正常工作,除非在更改后的第一个提示上,因为提示功能尚未执行。您可以优化它以仅在文件最近更改(例如最近 10 分钟)时重新加载模块。

    由于第一个提示可能有问题,因此有一些方法可以使其自动化:) 创建 Autohotkey 脚本来监视模块的更改并在检测到更改后发送到其控制台。如果你这样做了,那么你甚至不需要像你一样迅速改变 Send ipmo -force..使用 Autohotkey 本身。当我写这篇文章时,我很高兴,但它是史诗般的,如果 AHK 脚本正确完成,老实说它将完美地工作。

    我不确定是否有任何其他方法可以在事件 session 中自动重新加载模块,除非您使用一些怪异的东西,例如为所有 cmdlet 创建 powershell 代理,这些代理基本上与提示功能相同。但...

    编辑

    我发现这个东西是半相关的,但我仍然认为 AHK 解决方案是可行的

    https://stackoverflow.com/a/7341211/82660

    编辑2

    这是Ahk完成困难部分的脚本(我没有编写文件修改检查,这很简单):
    ;Find window
    SetTitleMatchMode, 2
    ise := WinExist("PowerShell ISE")
    WinGetPos, x,y,w,h
    
    ;Click somewhere inside console to select it
    x := x + 20
    y := h - 100  ;you may need to tweak this number depending on windows theme etc...
    WinActivate
    CoordMode, Mouse ,Screen
    Click %x%, %y%
    SendInput {ESC}import-module -force Configure-EngravePC{ENTER}
    

    脚本可能会更好,更精确,但我的 AHKfoo 现在很差......

    关于PowerShell:模块、它们的位置和重新加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29669927/

    相关文章:

    powershell - SendMessage 导致脚本挂起

    powershell-2.0 - 在 Windows 7 上使用 powershell 2.0 下载文件

    powershell - 从模块中导出 Powershell 5 枚举声明

    点源文件中的 PowerShell 点源 - 导入类

    具有在单独文件中定义的类的 PowerShell 模块未通过 GitHub Actions 中的 Pester 测试

    powershell - 在Powershell中需要一些逻辑来衡量最新

    powershell - 什么是 [cmdletbinding()] 以及它如何工作?

    powershell - 巡航控制和 Powershell

    powershell - 在powershell中隐藏标题栏

    powershell - 在 Powershell 中使用 HTML 创建表格