模块自动加载是否可靠?

Is module auto-loading meant to be reliable?

环境

我有以下存放 Powershell 模块的文件夹结构:

C:
  PsModules
     ...
     util
        util.psm1 (this contains implementation of 'Test-Function')
        util.test.ps1
     ftp
        ftp.psm1
        http.test.ps1
     ... 

c:\PsModules中有大约 50 个文件夹和模块。

我已将环境变量 PSModulePath 设置为包含 c:\PsModules。这似乎符合"well-formed modules" described in Microsoft's documentation and this answer.

的条件

症状

有时 Test-Function 在从 ISE 调用时不会自动找到。事实上,在任何给定的 ISE 新启动时,总​​会有一些(看似不可预测的)模块无法自动找到。自动查找Test-Function的失败,例如是这样的:

PS C:\> Test-Function
Test-Function : The term 'Test-Function' is not recognized as the name 
of a cmdlet, function, script file, or operable program. Check the 
spelling of the name, or if a path was included, verify that the path is 
correct and try again.
...
+ FullyQualifiedErrorId : CommandNotFoundException

乍一看,这似乎表明 util.psm1 不是 "well-formed"。如果不是 "well-formed",则 ListAvailable 不应该起作用。但它确实有效:

c:\> get-module -ListAvailable util
Directory: c:\PsModules\util

ModuleType Version    Name                 ExportedCommands
---------- -------    ----                 ----------------
Script     0.0        util

PS C:\> Test-Function
...
+ FullyQualifiedErrorId : CommandNotFoundException

另外,为模块调用Get-Command后,模块中的命令可以通用:

c:\> Get-Command -Module util
CommandType     Name                             ModuleName
-----------     ----                             ----------
Function        Test-Function                    util
c:\> Test-Function
Call to Test-Function succeeded!

问题

  1. 自动发现和模块自动加载应该是可靠和可预测的吗?

  2. 我如何解决为什么 powershell 有时在调用 Get-Command -module 之前找不到命令?

  3. 依赖powershell自动加载模块是不是不好的做法?如果是这样,自动加载模块的最佳做法是什么?

我不能说模块自动加载是否 打算 可靠,但我个人并不依赖它来完成代码。

如果我正在编写脚本或模块,我总是使用 Import-Module TheModule -ErrorAction Stop,并且经常使用 #Requires -Module AciveDirectory,TheModule,SQLPs 以确保模块可用。

为了在 PowerShell 控制台或 ISE 中进行交互式使用,我通常依靠自动加载,但如果它失败了,我只是 Import-Module 手动进行会话。

在我总是希望为交互式会话加载特定模块的情况下,我将其加载到配置文件中。要查看各种配置文件 运行 这个(来自 ISE 和控制台):

$profile | Get-Member -MemberType NoteProperty

您可以根据希望模块可用的用户和主机来决定将用于导入模块的代码放在哪里。

到目前为止,我只为 posh-git 执行此操作,但它似乎很适合您的用例。

如果这对其他人有帮助,我认为这可能是 ISE 独有的问题。我无法重现,但最近与 MS 讨论了不一致的 ISE 工作流行为,经过一些努力,这个问题在没有解决方案的情况下被解决了,官方的回答是不使用未经批准用于生产的 ISE,而是使用本机 shell.这对我们来说是一个现实的答案,从未在原生 shell 中看到问题。请问这个症状是不是一样?

我发现模块清单中的 FunctionsToExport 部分不能设置为 *

这很糟糕:

# Functions to export from this module, for best performance, do not use 
# wildcards and do not delete the entry, use an empty array if there are no 
# functions to export.
FunctionsToExport = '*'

这很好:

# Functions to export from this module...
FunctionsToExport = 'Test-Function, Test-Function2'