Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does #Requires work in module scripts?

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?

like image 428
jpmc26 Avatar asked Feb 16 '17 19:02

jpmc26


People also ask

What do we mean by does?

present tense third-person singular of do.

How use does in a sentence?

"She does her homework before she goes out to play." "She does many after school activities." "He does a lot of chores around the house." "He does the dishes every night."

Do it or does it?

“Does” is used for singular subjects like “he,” “she,” “it,” “this,” “that,” or “John.” “Do” is used to form imperative sentences, or commands.

What kind of word is do does?

The Verb to do: do, does and did They are all forms of the verb to do. The verb to do can be used as an action verb and also as an auxiliary verb.


1 Answers

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.

like image 68
jpmc26 Avatar answered Sep 23 '22 06:09

jpmc26