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

PowerShell: Modules, their locations, and reloading

我有一个非常简单的 PS 脚本,它引用了一堆自己编写的模块 (psm1)。当我 运行 来自 PowerShell ISE 的脚本时,我经常感到紧张,因为我的模块的最新版本没有被执行(但是一些过时的存储在内存中的版本)。

我有 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 将 运行 OLD模块的版本。

除非我通过以下任一方式重新加载模块:

将执行与我的模块完全相同的 "old" 版本。

谁能指点一下平时应该怎么处理? 为什么,为什么哦,为什么,当我通过调试器 运行 我的脚本时,我什至必须重新加载模块?为什么 "store" 模块在不同的会话中 运行?难道我做错了什么?

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

我非常喜欢有适当解释的答案(或参考有关此主题的 good 文档)

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

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

糟糕的解决方案是在您输入 ISE 时替换 prompt 函数(或将其添加到您的配置文件中):

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 本身。当我写这篇文章时,我 ROFLMAOd,但如果 AHK 脚本正确完成,它是史诗般的,老实说,它会完美地工作。

我不确定是否有任何其他方法可以在活动会话发生变化时自动重新加载模块,除非您使用一些奇怪的东西,例如为所有 cmdlet 创建 powershell 代理,这基本上会提前执行与提示功能相同的操作。但是...

编辑

我发现这个东西 semi-related,但我仍然认为 AHK 解决方案是可行的

EDIT2

这是执行困难部分的 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 现在很差...