【问题标题】:How can I reload modules from one open work environment to affect another working environment如何从一个开放的工作环境重新加载模块以影响另一个工作环境
【发布时间】:2011-12-23 14:30:41
【问题描述】:

我将 PowerShell 项目分解为多个模块。但是因为它们是模块,所以我每次更改它们时都必须重新加载它们。因此,我编写了一个具有 FileSystemWatcher 的循环,如果其中一个 .psm1 文件发生更改,它将重新加载或导入该模块。

问题是上述循环不会让我在其工作环境中运行其他脚本,因此新环境不会为其加载/重新加载相同的模块。我需要将这些模块保留在主要的默认 PowerShell 模块文件夹之外。当模块在同一环境中发生变化或影响特定环境时,有没有办法运行重新加载模块的脚本?


更新

所以我运行以下 Module-Loader.ps1 脚本。当我在修改后“保存”*.psm1 文件时,与“FileChanged”事件关联的代码块会触发。但是出现了两个问题: 1)当我保存时它会触发两次

2a) 如果模块未加载,它将运行 Import-Module $PWD\ModuleName,但至少在环境中实际上不会加载(如果我在环境中运行相同的代码,它将加载)

2b) 如果它被加载,并且它试图移除该模块,它会报错不存在。

# create a FileSystemWatcher on the currect directory
$filter = '*.psm1'
$folder = $PWD
$watcher = New-object IO.FileSystemWatcher $folder, $filter -Property @{IncludeSubdirectories = $false; EnableRaisingEvents = $true; NotifyFilter = [IO.NotifyFilters]'LastWrite'}
Register-ObjectEvent $watcher Changed -SourceIdentifier FileChanged -Action { 
$name = $Event.SourceEventArgs.Name 
$filename = $name.Remove($name.IndexOf('.'), 5)

$loadedModule = Get-Module | ? { $_.Name -eq $filename }
write-host $filename

if ($loadedModule) {
    write-host "Reloading Module $folder\$($filename)"
    Reload-Module $folder\$filename
} else {
    write-host "Importing Module $folder\$($filename)"
    Import-Module $folder\$filename
}
}

我认为虽然这是在会话中运行,但事件中的代码块与此特定环境无关。

【问题讨论】:

  • 我不太确定我是否理解您的问题。你是说,因为它是一个循环,它会阻止其他代码运行?如果是这样,您可以通过注册事件处理程序而不是使用循环来让文件系统观察程序异步触发脚本块。如果这听起来像你需要的,我可以给你一些示例代码。
  • @Andy:是的,因为它在一个循环中,它阻塞了其他代码。而且由于重新加载/导入模块只会在文件系统观察程序运行的当前环境中,我无法重新运行依赖于重新加载/导入模块的脚本。我不确定让手表触发事件是否会起作用,因为那时我必须硬编码这将是什么。但是,如果不是太多,您可以发布一些示例吗?

标签: powershell powershell-module


【解决方案1】:

这是我拥有的一些代码的示例,它可以在文件夹发生更改时将文件夹复制到共享文件夹。这有点像我的小 Dropbox 实现 :-)

任何时候出现诸如Changed 之类的文件系统观察程序事件类型,在Register-ObjectEvent cmdlet 的-Action 参数中指定的代码都会触发。

在您的-Action 代码中,您可以使用-Force 参数调用Import-Module 以覆盖当前的 记忆。

function Backup-Folder {
    & robocopy.exe "c:\folder" "\\server\share" /MIR /W:10 /R:10
}

$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "c:\folder"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true

Register-ObjectEvent $watcher "Changed" -Action { Backup-Folder }
Register-ObjectEvent $watcher "Created" -Action { Backup-Folder }
Register-ObjectEvent $watcher "Deleted" -Action { Backup-Folder }
Register-ObjectEvent $watcher "Renamed" -Action { Backup-Folder }

【讨论】:

  • 我采纳了您的建议并采取了同样的做法,我的 Action 基本上会检查模块是否已加载并导入或重新加载已更改的模块 (.psm1) 文件。但是,我发现执行代码块时返回的任何内容都不会加载模块 - 至少在运行脚本的环境中,将代码块绑定到事件。
  • 我试图查看是否有办法在代码块中传递特定于环境的信息并针对特定会话/环境加载模块
  • 如果我理解正确您所说的以下内容。 1. Import-Module 加载初始模块。 2.模块文件发生变化。 3. 事件处理程序触发脚本块。 4. 脚本块重新加载模块。 5.模块更改不生效。对吗?
  • 仅部分。 1) 从 PS env 运行监控当前目录的模块加载器脚本,如果 .psm1 文件发生更改,它会检查它是否已经加载并导入/重新加载。作为事件的代码块非常简单,它只是执行一个获取模块,其中 psm1 文件已更改,如果已加载,则重新加载,否则导入。但它评估模块已加载,但在尝试 reload-module 时会出现未加载的错误。
  • 您能否发布您的代码,以便我可以帮助您解决该错误?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-12
  • 2022-06-14
相关资源
最近更新 更多