Does #Requires work in module scripts?

丶灬走出姿态 提交于 2019-12-08 20:05:07

问题


Consider the following module script:

MyWebApp.psm1:

#Requires -Version 4
#Requires -Modules WebAdministration

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

(Export-ModuleMember omitted for simplicity. The script still works as a module without it.)

If this were a ps1 script, the #Requires comments at the top would force PowerShell to throw an error if

  • The version were lower than 4
  • The WebAdministration module could not be loaded (imported)

But if I try to import this using Import-Module, do these have any effect? The #Requires documentation just says "scripts", but it doesn't clarify whether script modules count as "scripts" or not here. What can I do instead, if not?


回答1:


No, it's treated as a normal comment

No, #Requires comments are not processed when a psm1 script is executed by calling Import-Module.

If we save the script in the question as both MyWebApp.psm1 and MyWebApp.ps1 on a machine that lacks the WebAdministration module, we get the following result:

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>

Importing the module succeeds, and the function now exists in the current scope. But the function will fail:

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

Even the -Version check is ignored. If we bump it up to 5 on a machine with only PowerShell 4:

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>

Use a Module Manifest

The only way to get the requirements validated properly is to use a module manifest. Unfortunately, this must be a separate file alongside the psm1 file. The following manifest will achieve what the #Requires comments are intended to do:

MyWebApp.psd1:

#
# Module manifest for module 'MyWebApp'
#

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

Importing this file gives the error we want:

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

Unfortunately, you cannot declare the function in the same file. You must use a separate psd1 file and then explicitly declare the original psm1 script as the "root module." The root module is indicated as a path relative to the psd1 file.

Other attributes:

  • The ModuleVersion is required. It must be present.
  • PowerShellVersion accomplishes what #Requires -Version 4 intends.
  • RequiredModules accomplishes what #Requires -Modules WebAdministration intends.

Note that Test-MyWebApp is exported implicitly in both the psm1 and the psd1 file. This is normally controlled by Export-ModuleMember -Function in a psm1 file; the equivalent in a module manifest is FunctionsToExport. I find it simpler to just omit FunctionsToExport from the manifest and control what's exported using Export-ModuleMember in the psm1 script.



来源:https://stackoverflow.com/questions/42283014/does-requires-work-in-module-scripts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!