DSCClassResources/PowershellModule/PowershellModule.psm1
#Requires -Version 5.0 <# .SYNOPSIS This module addresses the problem of managing Powershell modules. It was designed specifically to ensure that only a single version of a given module is installed in the AllUsers scope when Ensure is Present. .PARAMETER Name The name of a Powershell module. .PARAMETER RequiredVersion The version of a Powershell module. .PARAMETER Repository The location of a Powershell module. #> enum Ensure { Absent Present } [DscResource()] class PowershellModule { [DscProperty(Key)] [string] $Name [DscProperty()] [Ensure] $Ensure = "Present" [DscProperty()] [string] $RequiredVersion [DscProperty()] [string] $Repository = "PSGallery" [PowershellModule] Get() { $Module = Get-Module -Name $this.Name -ListAvailable | Where-Object { $_.RepositorySourceLocation } if ($Module) { $this.Name = $Module.Name $this.RequiredVersion = $Module.Version $this.Repository = $Module.RepositorySourceLocation } else { $this.Name = $null $this.RequiredVersion = $null $this.Repository = $null } return $this } [void] Set() { $PSBoundParameters = $this.GetPSBoundParameters() $Modules = Get-Module -Name $this.Name -ListAvailable | Where-Object { $_.RepositorySourceLocation } if ($this.Ensure -eq [Ensure]::Present) { if ($this.RequiredVersion -and ($Modules.Version -notcontains $this.RequiredVersion)) { Write-Verbose -Message "Installing module [$($this.Name)]." Install-Module @PSBoundParameters -Scope AllUsers -Force } } $PSBoundParameters.Remove('Repository') foreach ($Module in $Modules) { if ($this.Ensure -eq [Ensure]::Present) { if ($Module.Version -ne $this.RequiredVersion) { Write-Verbose -Message "Removing side-by-side module [$($Module.Name)] with version [$($Module.Version)]." Get-InstalledModule @PSBoundParameters | Uninstall-Module -Force } } elseif ($this.Ensure -eq [Ensure]::Absent) { Write-Verbose -Message "Removing module [$($Module.Name)]." Get-InstalledModule @PSBoundParameters | Uninstall-Module -Force } } } [bool] Test() { $Module = Get-Module -Name $this.Name -ListAvailable | Where-Object { $_.RepositorySourceLocation } $Result = $true if ($this.Ensure -eq [Ensure]::Present) { if ($Module.Count -ne 1) { Write-Verbose -Message "Expected a single instance of module [$($this.Name)] but was [$($Module.Count)]." $Result = $false } if ($this.RequiredVersion -and ($Module.Version -ne $this.RequiredVersion)) { Write-Verbose -Message "Expected module version [$($this.RequiredVersion)] but was [$($Module.Version)]." $Result = $false } if ($Module.Name -ne $this.Name) { Write-Verbose -Message "Expected module [$($this.Name)] but was [$($Module.Name)]." $Result = $false } } elseif ($this.Ensure -eq [Ensure]::Absent) { if ($Module.Count -gt 0) { Write-Verbose -Message "Expected no instances of module [$($this.Name)] but was [$($Module.Count)]." $Result = $false } } return $Result } # Helper method to mimic PSBoundParameters within class [hashtable]GetPSBoundParameters() { $PSBoundParameters = @{ Name = $this.Name; Repository = $this.Repository; } if ($this.RequiredVersion) { $PSBoundParameters["RequiredVersion"] = $this.RequiredVersion } return $PSBoundParameters } } |