问题
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