PSRequiredModules.psm1
<#
.SYNOPSIS Get-RequiredModules .DESCRIPTION Read PSRequiredModules data from PowerShell module manifest. .PARAMETER ModuleFilePath Module file path expect a module file ending with .psd1 or .psm1 (to retrieve automatically associated .psd1) .EXAMPLE PS C:\> Get-RequiredModules -ModuleFilePath 'C:\MyModule\MyModule.psd1' .INPUTS System.String .OUTPUTS System.Boolean .NOTES Author: JDMSFT Date: 17/03/21 #> Function Get-RequiredModules { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ModuleFilePath ) Try { If ($ModuleFilePath -like '*.psm1' -or $ModuleFilePath -like '*.psd1') { $ManifestData = Import-LocalizedData -BaseDirectory (Split-Path $ModuleFilePath) -FileName (Split-Path $ModuleFilePath -Leaf) $ManifestData.PrivateData.PSRequiredModules } Else { Write-Warning "Please specify a valid module file path (ending with .psm1/.psd1)" } } Catch { Write-Error $($_) ; throw "[message] $($_)`nException: [locator] $($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber) >> $($_.InvocationInfo.Line.TrimStart())" } } <# .SYNOPSIS Import-RequiredModules .DESCRIPTION Read PSRequiredModules data from PowerShell module manifest. .PARAMETER ModuleFilePath Module file path expect a module file ending with .psd1 or .psm1 (to retrieve automatically associated .psd1) .PARAMETER AutoInstall Automatically install missing module from PowerShell environments .PARAMETER Details Return full state details isntead returning a boolean (usefull to troubleshoot) .EXAMPLE PS C:\> Import-RequiredModules -ModuleFilePath 'C:\MyModule\MyModule.psd1' Return if all required modules are imported in the PowerShell session. .EXAMPLE PS C:\> Import-RequiredModules -ModuleFilePath 'C:\MyModule\MyModule.psd1' -AutoInstall Install missing modules and return if all required modules are imported in the PowerShell session. .EXAMPLE PS C:\> Import-RequiredModules -ModuleFilePath 'C:\MyModule\MyModule.psd1' -Details Return all required modules states for the current PowerShell session instead returnin a boolean. .INPUTS System.String .OUTPUTS System.Boolean,Hastable .NOTES Author: JDMSFT Date: 17/03/21 #> Function Import-RequiredModules { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ModuleFilePath, [switch]$AutoInstall, [switch]$Details ) Try { If ($ModuleFilePath -like '*.psm1' -or $ModuleFilePath -like '*.psd1') { $ModuleObject = @() $CallerFileName = (Split-Path $ModuleFilePath -Leaf) $CallerName = $CallerFileName.Substring(0, $CallerFileName.Length-5) $ManifestData = Import-LocalizedData -BaseDirectory (Split-Path $ModuleFilePath) -FileName $CallerFileName $CallerVersion = $ManifestData.ModuleVersion $ManifestData.PrivateData.PSRequiredModules.Keys | ForEach { $IsAlreadyImported = $false $IsRightVersionImported = $false $IsRightVersionInstalled = $false $IsDownloadable = 'Untested (locally present)' $Action = 'None' $State = $null # Get required version / prerelease $RequiredModuleName = $_ $RequiredModuleVersionSemVer = $ManifestData.PrivateData.PSRequiredModules.$_ If ($RequiredModuleVersionSemVer -like '*-*') { $PreReleaseVersion = $true $RequiredModuleVersion = ($RequiredModuleVersionSemVer -split '-')[0] $RequiredModulePrerelease = ($RequiredModuleVersionSemVer -split '-')[1] } Else { $PreReleaseVersion = $false $RequiredModuleVersion = $RequiredModuleVersionSemVer } # Checking for imported module version ... $MatchVersion = $false $RequiredModuleImportedMatches = Get-Module $RequiredModuleName If ($RequiredModuleImportedMatches) { If ($PreReleaseVersion) { Write-Verbose "Checking for imported module $RequiredModuleName v$RequiredModuleVersionSemVer... (prerelease)" $RequiredModuleImportedMatches | ForEach { If ($_.Version -eq $RequiredModuleVersion -and $_.PrivateData.PSData.Prerelease -eq $RequiredModulePrerelease) { Write-Verbose "Module $RequiredModuleName v$RequiredModuleVersionSemVer already imported !" $MatchVersion = $true $RequiredModule = $_ $IsAlreadyImported = $true $IsRightVersionImported = $true $IsRightVersionInstalled = $true $State = 'OK' } } } Else { Write-Verbose "Checking for imported module $RequiredModuleName v$RequiredModuleVersionSemVer... (not prerelease)" $RequiredModuleImportedMatches | ForEach { If ($_.Version -eq $RequiredModuleVersion) { Write-Verbose "Module $RequiredModuleName v$RequiredModuleVersionSemVer already imported !" $MatchVersion = $true $RequiredModule = $_ $IsAlreadyImported = $true $IsRightVersionImported = $true $IsRightVersionInstalled = $true $State = 'OK' } } } If ($MatchVersion -ne $true) { Write-Warning "[PSRequiredModules] Wrong $RequiredModuleName module version already imported in the current PowerShell session (required version : $RequiredModuleVersionSemVer). You may encount some issue/bug by using this $RequiredModuleName module version. Please consider to remove $RequiredModuleName module (Remove-Module $RequiredModuleName) from your current PowerShell session prior importing $CallerName v$CallerVersion for an optimal experience." $IsAlreadyImported = $true $Action = "Skipped" $State = 'Warning (wrong version already imported)' } } Else {Write-Verbose "No $RequiredModuleName imported in the current PowerShell session"} If ($IsAlreadyImported -ne $true) { # Checking for installed module version ... $RequiredModuleInstalledMatches = Get-Module $RequiredModuleName -ListAvailable If ($MatchVersion -ne $true) { If ($PreReleaseVersion) { Write-Verbose "Checking for installed module $RequiredModuleName v$RequiredModuleVersionSemVer... (prerelease)" $RequiredModuleInstalledMatches | ForEach { If ($_.Version -eq $RequiredModuleVersion -and $_.PrivateData.PSData.Prerelease -eq $RequiredModulePrerelease) { Write-Verbose "Module $RequiredModuleName v$RequiredModuleVersionSemVer already installed !" $MatchVersion = $true $RequiredModule = $_ $IsRightVersionInstalled = $true } } } Else { Write-Verbose "Checking for installed module $RequiredModuleName v$RequiredModuleVersionSemVer... (not prerelease)" $RequiredModuleInstalledMatches | ForEach { If ($_.Version -eq $RequiredModuleVersion) { Write-Verbose "Module $RequiredModuleName v$RequiredModuleVersionSemVer already installed !" $MatchVersion = $true $RequiredModule = $_ $IsRightVersionInstalled = $true } } } # Module installed, importing ... If ($MatchVersion -eq $true) { Write-Verbose "Importing module $RequiredModuleName v$RequiredModuleVersionSemVer..." Import-Module $RequiredModule -Global $Action = 'AutoImport' If (Get-Module $RequiredModuleName) { $State = 'OK' } Else { $State = 'KO' } } # Module not installed, installing and importing ... Else { Write-Verbose "Module $RequiredModuleName v$RequiredModuleVersionSemVer not found." If (Find-Module -Name $RequiredModuleName -RequiredVersion $RequiredModuleVersionSemVer -Repository PSGallery -AllowPrerelease -ea SilentlyContinue) { $IsDownloadable = $true } Else { $IsDownloadable = $false } If ($AutoInstall) { If ($IsDownloadable) { $Action = 'AutoInstall' Install-Module -Name $RequiredModuleName -RequiredVersion $RequiredModuleVersionSemVer -Repository PSGallery -AllowPrerelease If (Get-InstalledModule -Name $RequiredModuleName -RequiredVersion $RequiredModuleVersionSemVer -AllowPrerelease -ea SilentlyContinue) { Import-Module -Name $RequiredModuleName -RequiredVersion $RequiredModuleVersion -Global } } Else { Write-Verbose "$RequiredModuleName can't be downloaded." } If (Get-Module $RequiredModuleName) { $State = 'OK' } Else { $State = 'KO' } } Else { Write-Verbose "Auto-install module disabled. Please installl required module manually prior using this module : Isntall-Module -Name $ModuleName -RequiredVersion $RequiredModuleVersionSemVer" ; $State = 'KO' } } } Else { Write-Verbose "" } } $ModuleObject += [PSCustomObject]@{Name = $RequiredModuleName; Version = $RequiredModuleVersionSemVer; IsPrerelease = $PreReleaseVersion ; IsAlreadyImported = $IsAlreadyImported ; IsRightVersionImported = $IsRightVersionImported ; IsRightVersionInstalled = $IsRightVersionInstalled ; IsDownloadable = $IsDownloadable ; Action = $Action ; State = $State } } If ($Details) { $ModuleObject } Else { $ModuleObject.State -notcontains 'KO' } } Else { Write-Warning "Please specify a valid module file path (ending with .psm1/.psd1)" } } Catch { Write-Error $($_) ; throw "[message] $($_)`nException: [locator] $($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber) >> $($_.InvocationInfo.Line.TrimStart())" } } |