DSCResources/ProfileFever_PSModule/ProfileFever_PSModule.psm1
Import-Module -Name 'PackageManagement' -Verbose:$false function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [parameter(Mandatory = $false)] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', [parameter(Mandatory = $true)] [System.String] $Name, [parameter(Mandatory = $true)] [System.String] $Version, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.String] $Repository = 'PSGallery' ) # Detect the latest version from the repository if ($Version -eq 'latest') { $Version = Get-LatestModuleVersion -Name $Name -Repository $Repository } Write-Verbose "Get the current state: Name = $Name, Version = $Version" try { $module = Get-InstalledModule -Name $Name -RequiredVersion $Version -ErrorAction Stop # Return the installed module return @{ Ensure = 'Present' Name = $module.Name Version = $module.Version Repository = $module.Repository } } catch { # No module was found, return absent return @{ Ensure = 'Absent' Name = $Name Version = $Version Repository = '' } } } function Set-TargetResource { [CmdletBinding()] [OutputType([void])] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] param ( [parameter(Mandatory = $false)] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', [parameter(Mandatory = $true)] [System.String] $Name, [parameter(Mandatory = $true)] [System.String] $Version, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.String] $Repository = 'PSGallery' ) # Detect the latest version from the repository if ($Version -eq 'latest') { $Version = Get-LatestModuleVersion -Name $Name -Repository $Repository } $module = Get-TargetResource @PSBoundParameters # The module must be present if ($Ensure -eq 'Present' -and $module.Ensure -eq 'Absent') { Write-Verbose "Ensure the module is installed: Name = $Name, Version = $Version" # Install the target version Install-ModuleVersion -Name $Name -Version $Version -Repository $Repository } # The module must be absent if ($Ensure -eq 'Absent' -and $module.Ensure -eq 'Present') { Write-Verbose "Ensure the module is not installed: Name = $Name, Version = $Version" # Remove the installed module version because it's present Uninstall-ModuleVersion -Name $Name -Version $Version } } function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [parameter(Mandatory = $false)] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', [parameter(Mandatory = $true)] [System.String] $Name, [parameter(Mandatory = $true)] [System.String] $Version, [parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.String] $Repository = 'PSGallery' ) # Detect the latest version from the repository if ($Version -eq 'latest') { $Version = Get-LatestModuleVersion -Name $Name -Repository $Repository } $module = Get-TargetResource @PSBoundParameters Write-Verbose "Test the current state: Name = $Name, Version = $Version" if ($Ensure -eq 'Present') { $result = $Ensure -eq $module.Ensure -and $Repository -eq $module.Repository } else { $result = $Ensure -eq $module.Ensure } return $result } function Get-LatestModuleVersion($Name, $Repository) { $cachePath = Join-Path -Path $Env:ProgramData -ChildPath 'PowerShell\Modules\ProfileFever' $cacheFile = Join-Path -Path $cachePath -ChildPath "$Name.xml" # Create the cache path if (!(Test-Path -Path $cachePath)) { New-Item -Path $cachePath -ItemType Directory | Out-Null } # Check for the cache file if ((Test-Path -Path $cacheFile)) { $cacheData = Import-Clixml -Path $cacheFile if ($cacheData.Timestamp -gt (Get-Date).AddDays(-1)) { Write-Verbose "Cached version found: Timestamp = $($cacheData.Timestamp), Version = $($cacheData.Version)" return $cacheData.Version } } Write-Verbose "Detect latest version in $Repository`: Name = $Name" $module = Find-Module -Name $Name -Repository $Repository -ErrorAction Stop $version = [String] $module.Version Write-Verbose "Detect latest version in $Repository`: Name = $Name, Version = $version" # Update cache [PSCustomObject] @{ Timestamp = [DateTime]::Now; Version = $version } | Export-Clixml -Path $cacheFile return $version } function Install-ModuleVersion($Name, $Version, $Repository) { Write-Verbose "Install module from $Repository`: Name = $Name, Version = $Version" Install-Module -Name $Name -RequiredVersion $Version -Repository $Repository -Force -AllowClobber -SkipPublisherCheck } function Uninstall-ModuleVersion($Name, $Version) { Write-Verbose "Uninstall module: Name = $Name, Version = $Version" Uninstall-Module -Name $Name -RequiredVersion $Version -Force } Export-ModuleMember -Function *-TargetResource |