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

时间:2015-04-16 08:58:56

标签: powershell powershell-v2.0 powershell-module

我有一个非常简单的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"时,按下Save按钮,再次调试我的主脚本(上面显示的脚本),PowerShell将运行该模块的 OLD 版本。

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

  • rmo Configure-EngravePC后跟ipmo Configure-EngravePC
  • ipmo Configure-EngravePC -Force

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

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

许多人提前感谢,我希望有人可以详细说明这一点,我常常陷入困境......

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

1 个答案:

答案 0 :(得分:1)

您需要重启ISE,因为它保留了单一控制台AFAIK。

现在,为了在没有重新启动的情况下执行此操作,您将不得不创建新的ISE Runspace(文件>新的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脚本,监视模块的更改并在检测到更改后发送到其控制台。如果你这样做,那么甚至不需要快速更改,因为你可以使用Autohotkey本身Send ipmo -force..。当我写这篇文章的时候我是ROFLMAOd,但是如果AHK脚本正确完成,它的史诗和完美的工作将是完美的。

我不确定是否有任何其他方法可以在活动会话中自动重新加载模块,除非你使用一些奇怪的东西,比如为所有cmdlet创建powershell代理,它基本上会提前做与提示函数相同的操作。但是......

修改

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

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

<强> 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现在很差......