#Requires 在模块脚本中工作吗?

Does #Requires work in module scripts?

考虑以下模块脚本:

MyWebApp.psm1:

#Requires -Version 4
#Requires -Modules WebAdministration

function Test-MyWebApp() {
    return ((Get-WebApplication 'myapp') -ne $null)
}

(为简单起见省略了Export-ModuleMember。脚本在没有它的情况下仍然作为一个模块工作。)

如果这是一个 ps1 脚本,顶部的 #Requires 注释将强制 PowerShell 在

时抛出错误

但是如果我尝试使用 Import-Module 导入它,这些有什么影响吗? The #Requires documentation 只是说 "scripts",但这里并没有说明脚本模块是否算作 "scripts"。如果不行,我能做什么?

否,按普通评论处理

否,当通过调用 Import-Module 执行 psm1 脚本时,不会处理 #Requires 注释。

如果我们在缺少 WebAdministration 模块的机器上将问题中的脚本同时保存为 MyWebApp.psm1MyWebApp.ps1,我们将得到以下结果:

PS> .\MyWebApp.ps1
.\MyWebApp.ps1 : The script 'MyWebApp.ps1' cannot be run because the following modules that are specified by the
"#requires" statements of the script are missing: WebAdministration.
At line:1 char:1
+ .\MyWebApp.ps1
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (MyWebApp.ps1:String) [], ScriptRequiresException
    + FullyQualifiedErrorId : ScriptRequiresMissingModules

PS> Import-Module .\MyWebApp.psm1
PS>

导入模块成功,函数现在存在于当前作用域中。但是函数会失败:

PS> Test-MyWebApp
Get-WebApplication : The term 'Get-WebApplication' 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.
At .\MyWebApp.psm1:5 char:14
+     return ((Get-WebApplication 'myapp') -Eq $null)
+              ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-WebApplication:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

甚至 -Version 检查也会被忽略。如果我们在只有 PowerShell 4 的机器上将它提高到 5:

PS> .\MyWebApp.ps1
.\MyWebApp.ps1 : The script 'MyWebApp.ps1' cannot be run because it contained a "#requires" statement for Windows
PowerShell 5.0. The version of Windows PowerShell that is required by the script does not match the currently running
version of Windows PowerShell 4.0.
At line:1 char:1
+ .\MyWebApp.ps1
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (MyWebApp.ps1:String) [], ScriptRequiresException
    + FullyQualifiedErrorId : ScriptRequiresUnmatchedPSVersion

PS> Import-Module .\MyWebApp.psm1
PS>

使用模块清单

正确验证需求的唯一方法是使用 module manifest。不幸的是,这必须是 psm1 文件旁边的一个单独文件。以下清单将实现 #Requires 注释的目的:

MyWebApp.psd1:

#
# Module manifest for module 'MyWebApp'
#

@{
ModuleVersion = '1.0'
PowerShellVersion = '4.0'
RequiredModules = @('WebAdministration')
RootModule = @('.\MyWebApp.psm1')
}

导入此文件会出现我们想要的错误:

PS> Import-Module .\MyWebApp.psd1
Import-Module : The required module 'WebAdministration' is not loaded. Load the module or remove the module from 'RequiredModules' in the file 
'.\MyWebApp.psd1'.
At line:1 char:1
+ Import-Module .\MyWebApp.psd1
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (.\MyWebApp.psd1:String) [Import-Module], MissingMemberException
    + FullyQualifiedErrorId : Modules_InvalidManifest,Microsoft.PowerShell.Commands.ImportModuleCommand

遗憾的是,您不能在同一个文件中声明该函数。您必须使用 单独的 psd1 文件,然后将原始 psm1 脚本显式声明为 "root module." 根模块表示为 相对于 psd1 文件的路径

其他属性:

  • ModuleVersion 是必需的。它必须存在。
  • PowerShellVersion 实现了 #Requires -Version 4 的意图。
  • RequiredModules 实现了 #Requires -Modules WebAdministration 的意图。

请注意 Test-MyWebApppsm1psd1 文件中隐式导出。这通常由 psm1 文件中的 Export-ModuleMember -Function 控制;模块清单中的等效项是 FunctionsToExport。我发现从清单中省略 FunctionsToExport 并在 psm1 脚本中使用 Export-ModuleMember 控制导出的内容更简单。