├── .github └── workflows │ └── publish.yml ├── .gitignore ├── LICENSE ├── MaintainModule ├── MaintainModule.psd1 └── MaintainModule.psm1 ├── README.md ├── publish.ps1 └── test ├── PSScriptAnalyzer_MaintainModule.psd1_2023-01-19.md ├── PSScriptAnalyzer_MaintainModule.psm1_2023-01-19.md ├── PSScriptAnalyzer_Uninstall-RSModule_2023-01-19.md └── PSScriptAnalyzer_Update-RSModule_2023-01-19.md /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build: 9 | name: Publish 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v1 13 | - name: Publish 14 | env: 15 | PSGALLERY: ${{ secrets.PSGALLERY }} 16 | run: .\publish.ps1 17 | shell: pwsh -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Packages # 2 | ############ 3 | # it's better to unpack these files and commit the raw source 4 | # git has its own built in compression methods 5 | *.7z 6 | *.dmg 7 | *.gz 8 | *.iso 9 | *.jar 10 | *.rar 11 | *.tar 12 | *.zip 13 | 14 | # Logs and databases # 15 | ###################### 16 | *.log 17 | *.sql 18 | *.sqlite 19 | 20 | # OS generated files # 21 | ###################### 22 | .DS_Store 23 | .DS_Store? 24 | ._* 25 | .Spotlight-V100 26 | .Trashes 27 | ehthumbs.db 28 | Thumbs.db 29 | *.csproj.user 30 | bin/ 31 | obj/ 32 | .vs/ 33 | .vscode/ 34 | .idea/ 35 | license/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2025 Robin Widmark. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MaintainModule/MaintainModule.psd1: -------------------------------------------------------------------------------- 1 | <# 2 | MIT License 3 | 4 | Copyright (C) 2025 Robin Widmark. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | #> 24 | 25 | # 26 | # Module manifest for module 'MaintainModule' 27 | # 28 | # Generated by: Robin Widmark 29 | # 30 | # Generated on: 2025-05-20 31 | # 32 | 33 | @{ 34 | 35 | # Script module or binary module file associated with this manifest. 36 | RootModule = '.\MaintainModule.psm1' 37 | 38 | # Version number of this module. 39 | ModuleVersion = '2.0.5' 40 | 41 | # Supported PSEditions 42 | # CompatiblePSEditions = @() 43 | 44 | # ID used to uniquely identify this module 45 | GUID = '4fec1769-909e-44cf-b715-bbc6b10564b3' 46 | 47 | # Author of this module 48 | Author = 'Robin Widmark' 49 | 50 | # Company or vendor of this module 51 | CompanyName = 'Widmark.dev' 52 | 53 | # Copyright statement for this module 54 | Copyright = '(c) 2025 Robin Widmark. All rights reserved.' 55 | 56 | # Description of the functionality provided by this module 57 | Description = 'This module let you maintain/update your installed PowerShell modules in a easy way' 58 | 59 | # Minimum version of the PowerShell engine required by this module 60 | PowerShellVersion = '5.1' 61 | 62 | # Name of the PowerShell host required by this module 63 | # PowerShellHostName = '' 64 | 65 | # Minimum version of the PowerShell host required by this module 66 | # PowerShellHostVersion = '' 67 | 68 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 69 | # DotNetFrameworkVersion = '' 70 | 71 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 72 | # ClrVersion = '' 73 | 74 | # Processor architecture (None, X86, Amd64) required by this module 75 | # ProcessorArchitecture = '' 76 | 77 | # Modules that must be imported into the global environment prior to importing this module 78 | # RequiredModules = @() 79 | 80 | # Assemblies that must be loaded prior to importing this module 81 | # RequiredAssemblies = @() 82 | 83 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 84 | # ScriptsToProcess = @() 85 | 86 | # Type files (.ps1xml) to be loaded when importing this module 87 | # TypesToProcess = @() 88 | 89 | # Format files (.ps1xml) to be loaded when importing this module 90 | # FormatsToProcess = @() 91 | 92 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 93 | # NestedModules = @() 94 | 95 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 96 | FunctionsToExport = "Uninstall-rsModule", "Update-rsModule", "Get-rsInstalledModule", "Test-rsComponent" 97 | 98 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 99 | CmdletsToExport = @() 100 | 101 | # Variables to export from this module 102 | VariablesToExport = '*' 103 | 104 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 105 | AliasesToExport = @() 106 | 107 | # DSC resources to export from this module 108 | # DscResourcesToExport = @() 109 | 110 | # List of all modules packaged with this module 111 | # ModuleList = @() 112 | 113 | # List of all files packaged with this module 114 | FileList = @("MaintainModule.psd1", "MaintainModule.psm1") 115 | 116 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 117 | PrivateData = @{ 118 | 119 | PSData = @{ 120 | 121 | # Tags applied to this module. These help with module discovery in online galleries. 122 | Tags = @("PowerShell", "macOS", "Windows", "Linux", "support-tool", "sysadmin-tool", "it-tool", "maintain-module", "module-maintenance", "multi-platform", "multiOS") 123 | 124 | # A URL to the license for this module. 125 | LicenseUri = 'https://github.com/rwidmark/MaintainModule/blob/main/LICENSE' 126 | 127 | # A URL to the main website for this project. 128 | ProjectUri = 'https://github.com/rwidmark/MaintainModule' 129 | 130 | # A URL to an icon representing this module. 131 | # IconUri = '' 132 | 133 | # ReleaseNotes of this module 134 | ReleaseNotes = 'https://github.com/rwidmark/MaintainModule/releases' 135 | 136 | # Prerelease string of this module 137 | Prerelease = 'beta' 138 | 139 | # Flag to indicate whether the module requires explicit user acceptance for install/update/save 140 | RequireLicenseAcceptance = $false 141 | 142 | # External dependent modules of this module 143 | #ExternalModuleDependencies = "rsServiceModule" 144 | 145 | } # End of PSData hashtable 146 | 147 | } # End of PrivateData hashtable 148 | 149 | # HelpInfo URI of this module 150 | # HelpInfoURI = '' 151 | 152 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 153 | # DefaultCommandPrefix = '' 154 | } 155 | -------------------------------------------------------------------------------- /MaintainModule/MaintainModule.psm1: -------------------------------------------------------------------------------- 1 | <# 2 | MIT License 3 | 4 | Copyright (C) 2025 Robin Widmark. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | #> 24 | Function Uninstall-rsModule { 25 | <# 26 | .SYNOPSIS 27 | Uninstall older versions of your modules in a easy way. 28 | 29 | .DESCRIPTION 30 | This script let users uninstall older versions of the modules that are installed on the system. 31 | 32 | .PARAMETER Module 33 | Specify modules that you want to uninstall older versions from, if this is left empty all of the older versions of the systems modules will be uninstalled 34 | 35 | .EXAMPLE 36 | Uninstall-rsModule -Module "VMWare.PowerCLI" 37 | # This will uninstall all older versions of the module VMWare.PowerCLI system. 38 | 39 | .EXAMPLE 40 | Uninstall-rsModule -Module "VMWare.PowerCLI", "ImportExcel" 41 | # This will uninstall all older versions of VMWare.PowerCLI and ImportExcel from the system. 42 | 43 | .EXAMPLE 44 | Uninstall-rsModule 45 | # This will uninstall all older versions of all modules in the system 46 | 47 | .LINK 48 | https://github.com/rwidmark/MaintainModule/blob/main/README.md 49 | 50 | .NOTES 51 | Author: Robin Widmark 52 | Mail: robin@widmark.dev 53 | Website/Blog: https://widmark.dev 54 | X: https://x.com/widmark_robin 55 | Mastodon: https://mastodon.social/@rwidmark 56 | YouTube: https://www.youtube.com/@rwidmark 57 | Linkedin: https://www.linkedin.com/in/rwidmark/ 58 | GitHub: https://github.com/rwidmark 59 | #> 60 | 61 | [CmdletBinding(SupportsShouldProcess)] 62 | Param( 63 | [Parameter(Mandatory = $false, HelpMessage = "Enter the module or modules you want to uninstall older version of, if not used all older versions will be uninstalled")] 64 | [string]$Module, 65 | [Parameter(Mandatory = $false, HelpMessage = ".")] 66 | [string[]]$OldVersion, 67 | [Parameter(Mandatory = $false, HelpMessage = "If this is used updates etc. be for prerelease")] 68 | [bool]$AllowPrerelease = $false 69 | ) 70 | 71 | Write-Output "START - Uninstall older versions of $($Module)" 72 | Write-Output "Please wait, this can take some time..." 73 | 74 | foreach ($_version in $OldVersion) { 75 | Write-Verbose "Uninstalling version $($_version) of $($Module)..." 76 | try { 77 | Uninstall-Module -Name $Module -RequiredVersion $_version -AllowPrerelease:$AllowPrerelease -Force -ErrorAction SilentlyContinue 78 | } 79 | catch { 80 | Write-Error "$($PSItem.Exception)" 81 | continue 82 | } 83 | } 84 | Write-Output "FINISHED - All older versions of $($Module) are now uninstalled!" 85 | } 86 | Function Get-rsInstalledModule { 87 | [CmdletBinding(SupportsShouldProcess)] 88 | Param( 89 | [Parameter(Mandatory = $false, HelpMessage = "Enter module or modules that you want to update, if you don't enter any, all of the modules will be updated")] 90 | [string[]]$Module 91 | ) 92 | 93 | $ReturnCode = 0 94 | $ReturnData = [ordered]@{} 95 | 96 | # Collect all installed modules from the system 97 | Write-Verbose "Caching all installed modules from the system..." 98 | $GetInstalledModules = Get-InstalledModule | Select-Object Name | Sort-Object -Descending 99 | 100 | if ([string]::IsNullOrEmpty($Module)) { 101 | Write-Verbose "Parameter Module are empty, populate it with all installed modules from the system..." 102 | $ReturnModule = foreach ($_module in $GetInstalledModules) { 103 | Write-Verbose "Collecting information about module $($_module.name)..." 104 | $GetAllInstalledVersions = Get-InstalledModule -Name $_module.name -AllVersions | Sort-Object { $_.Version -as [version] } -Descending 105 | 106 | # Get latest version 107 | [version]$LatestVersion = $($GetAllInstalledVersions | Select-Object Version -First 1).version 108 | 109 | # Get get all old versions 110 | [version]$OldVersions = $GetAllInstalledVersions | Where-Object { $_.Version -ne $LatestVersion } | Select-Object -ExpandProperty Version 111 | 112 | [PSCustomObject]@{ 113 | Name = $_module.Name 114 | Repository = $GetAllInstalledVersions.Repository 115 | OldVersion = $OldVersions 116 | LatestVersion = $LatestVersion 117 | } 118 | } 119 | } 120 | else { 121 | Write-Verbose "Looking so the modules exists in the system..." 122 | $ReturnModule = foreach ($_module in $Module) { 123 | if ($_module -in $GetInstalledModules.name) { 124 | Write-Verbose "$($_module) is installed, collecting information about it..." 125 | $GetAllInstalledVersions = Get-InstalledModule -Name $_module -AllVersions | Sort-Object { $_.Version -as [version] } -Descending 126 | 127 | # Get latest version 128 | [version]$LatestVersion = $($GetAllInstalledVersions | Select-Object Version -First 1).version 129 | 130 | # Get get all old versions 131 | [version]$OldVersions = $GetAllInstalledVersions | Where-Object { $_.Version -ne $LatestVersion } | Select-Object -ExpandProperty Version 132 | 133 | [PSCustomObject]@{ 134 | Name = $_module 135 | Repository = $GetAllInstalledVersions.Repository 136 | OldVersion = $OldVersions 137 | LatestVersion = $LatestVersion 138 | } 139 | } 140 | else { 141 | Write-Warning "$($_module) is not installed, skipping this module..." 142 | } 143 | } 144 | } 145 | 146 | if ($null -eq $ReturnModule) { 147 | $ReturnCode = 1 148 | Write-Warning "No modules was found..." 149 | $ReturnModule = $null 150 | } 151 | 152 | $ReturnData.Add("ReturnCode", $ReturnCode) 153 | $ReturnData.Add("Module", $ReturnModule) 154 | 155 | return $ReturnData 156 | } 157 | Function Test-rsComponent { 158 | [CmdletBinding(SupportsShouldProcess)] 159 | Param( 160 | 161 | ) 162 | 163 | # Making sure that TLS 1.2 is used. 164 | Write-Verbose "Making sure that TLS 1.2 is used..." 165 | [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 166 | 167 | # Checking if PSGallery are set to trusted 168 | Write-Verbose "Checking if PowerShell Gallery are set to trusted..." 169 | if ((Get-PSRepository -name PSGallery | Select-Object InstallationPolicy -ExpandProperty InstallationPolicy) -eq "Untrusted") { 170 | try { 171 | Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 172 | Write-Output "PowerShell Gallery was not set as trusted, it's now set as trusted!" 173 | } 174 | catch { 175 | Write-Error "$($PSItem.Exception)" 176 | continue 177 | } 178 | } 179 | else { 180 | Write-Verbose "PowerShell Gallery was already set to trusted, continuing!" 181 | } 182 | } 183 | Function Update-rsModule { 184 | <# 185 | .SYNOPSIS 186 | This module let you maintain your installed modules in a easy way. 187 | 188 | .DESCRIPTION 189 | This function let you update all of your installed modules and also uninstall the old versions to keep things clean. 190 | You can also specify module or modules that you want to update. It's also possible to install the module if it's missing and import the modules in the end of the script. 191 | 192 | .PARAMETER Module 193 | Specify the module or modules that you want to update, if you don't specify any module all installed modules are updated 194 | 195 | .PARAMETER Scope 196 | Need to specify scope of the installation/update for the module, either AllUsers or CurrentUser. Default is CurrentUser. 197 | If this parameter is empty it will use CurrentUser 198 | The parameter -Scope don't effect the uninstall-module function this is because of limitation from Microsoft. 199 | - Scope effect Install/update module function. 200 | 201 | .PARAMETER UninstallOldVersion 202 | If this switch are used all of the old versions of your modules will get uninstalled and only the current version will be installed 203 | 204 | .PARAMETER InstallMissing 205 | If you use this switch and the modules that are specified in the Module parameter are not installed on the system they will be installed. 206 | 207 | .PARAMETER AllowPrerelease 208 | If you set this to $true Pre-Releases are going to be installed / updated 209 | 210 | .PARAMETER SkipPublisherCheck 211 | If you set this to $true PublisherCheck will be ignored, this is something that for example are needed for Pester and PowerCLI because there certificate are not valid for some reason. 212 | 213 | .EXAMPLE 214 | Update-rsModule -Module "PowerCLI", "ImportExcel" -Scope "CurrentUser" 215 | # This will update the modules PowerCLI, ImportExcel for the current user 216 | 217 | .EXAMPLE 218 | Update-rsModule -Module "PowerCLI", "ImportExcel" -UninstallOldVersion 219 | # This will update the modules PowerCLI, ImportExcel and delete all of the old versions that are installed of PowerCLI, ImportExcel. 220 | 221 | .EXAMPLE 222 | Update-rsModule -Module "PowerCLI", "ImportExcel" -InstallMissing 223 | # This will install the modules PowerCLI and/or ImportExcel on the system if they are missing, if the modules are installed already they will only get updated. 224 | 225 | .EXAMPLE 226 | Update-rsModule -Module "PowerCLI", "ImportExcel" -UninstallOldVersion -ImportModule 227 | # This will update the modules PowerCLI and ImportExcel and delete all of the old versions that are installed of PowerCLI and ImportExcel and then import the modules. 228 | 229 | .LINK 230 | https://github.com/rwidmark/MaintainModule/blob/main/README.md 231 | 232 | .NOTES 233 | Author: Robin Widmark 234 | Mail: robin@widmark.dev 235 | Website/Blog: https://widmark.dev 236 | X: https://x.com/widmark_robin 237 | Mastodon: https://mastodon.social/@rwidmark 238 | YouTube: https://www.youtube.com/@rwidmark 239 | Linkedin: https://www.linkedin.com/in/rwidmark/ 240 | GitHub: https://github.com/rwidmark 241 | #> 242 | 243 | [CmdletBinding(SupportsShouldProcess)] 244 | Param( 245 | [Parameter(Mandatory = $false, HelpMessage = "Enter module or modules that you want to update, if you don't enter any, all of the modules will be updated")] 246 | [string[]]$Module, 247 | [Parameter(Mandatory = $false, HelpMessage = "Enter CurrentUser or AllUsers depending on what scope you want to change your modules, default is CurrentUser")] 248 | [ValidateSet("CurrentUser", "AllUsers")] 249 | [string]$Scope = "CurrentUser", 250 | [Parameter(Mandatory = $false, HelpMessage = "Uninstalls all old versions of the modules")] 251 | [switch]$UninstallOldVersion = $false, 252 | [Parameter(Mandatory = $false, HelpMessage = "Install all of the modules that has been entered in module that are not installed on the system")] 253 | [switch]$InstallMissing = $false, 254 | [Parameter(Mandatory = $false, HelpMessage = "Don't check publishers certificate")] 255 | [switch]$SkipPublisherCheck = $false, 256 | [Parameter(Mandatory = $false, HelpMessage = "If this is used updates etc. be for prerelease")] 257 | [bool]$AllowPrerelease = $false 258 | ) 259 | 260 | Write-Output "`n=== Module Maintenance - Widmark.dev 2025 ===" 261 | Write-Output "Please wait, this can take some time...`n" 262 | 263 | # Making sure that all needed components are installed 264 | Test-rsComponent 265 | 266 | Write-Output "START - Updating modules`n" 267 | 268 | # Collect all installed modules from the system 269 | $GetModuleInfo = Get-rsInstalledModule -Module $Module 270 | 271 | # Start looping trough every module that are stored in the string Module 272 | if ($GetModuleInfo.ReturnCode -eq 0) { 273 | foreach ($_module in $GetModuleInfo.Module) { 274 | # Getting the latest installed version of the module 275 | Write-Verbose "Collecting all installed version of $($_module.Name)..." 276 | 277 | # Collects the latest version of module from the source where the module was installed from 278 | Write-Verbose "Looking up the latest version of $($_module)..." 279 | [version]$CollectLatestVersion = $(Find-Module -Name $_module.Name -Repository $_module.Repository -AllVersions | Sort-Object { $_.Version -as [version] } -Descending | Select-Object Version -First 1).version 280 | 281 | # Looking if the version of the module are the latest version, it it's not the latest it will install the latest version. 282 | if ($_module.LatestVersion -lt $CollectLatestVersion) { 283 | try { 284 | Write-Output "Found a newer version of $($_module.Name), version $CollectLatestVersion" 285 | Write-Output "Updating $($_module.Name) from $($_module.LatestVersion) to version $CollectLatestVersion..." 286 | if ($SkipPublisherCheck -eq $true) { 287 | Update-Module -Name $_module.Name -Scope $Scope -AllowPrerelease:$AllowPrerelease -SkipPublisherCheck -AcceptLicense -Force 288 | } 289 | else { 290 | Update-Module -Name $_module.Name -Scope $Scope -AllowPrerelease:$AllowPrerelease -AcceptLicense -Force 291 | } 292 | Write-Output "$($_module.Name) has now been updated to version $($CollectLatestVersion)!" 293 | 294 | # If switch -UninstallOldVersion has been used then the old versions will be uninstalled from the module 295 | if ($UninstallOldVersion -eq $true -and $_module.OldVersion.Count -gt 0) { 296 | Uninstall-rsModule -Module $_module.Name -OldVersion $_module.OldVersion -AllowPrerelease:$AllowPrerelease 297 | Uninstall-rsModule -Module $_module.Name -OldVersion $_module.LatestVersion -AllowPrerelease:$AllowPrerelease 298 | } 299 | else { 300 | Write-Verbose "$($_module.Name) don't have any older versions to uninstall!" 301 | } 302 | } 303 | catch { 304 | Write-Error "$($PSItem.Exception)" 305 | continue 306 | } 307 | } 308 | else { 309 | Write-Verbose "$($_module.Name) are already up to date!" 310 | } 311 | } 312 | } 313 | #Install module if they want that 314 | else { 315 | # If the switch InstallMissing are set to true the modules will get installed if they are missing 316 | if ($InstallMissing -eq $true) { 317 | try { 318 | Write-Output "$($_module.name) are not installed, installing $($_module.name)..." 319 | if ($SkipPublisherCheck -eq $true) { 320 | Install-Module -Name $_module.name -Scope $Scope -AllowPrerelease:$AllowPrerelease -SkipPublisherCheck -AcceptLicense -Force 321 | } 322 | else { 323 | Install-Module -Name $_module.name -Scope $Scope -AllowPrerelease:$AllowPrerelease -AcceptLicense -Force 324 | } 325 | Write-Output "$($_module.name) has now been installed!" 326 | } 327 | catch { 328 | Write-Error "$($PSItem.Exception)" 329 | continue 330 | } 331 | } 332 | else { 333 | Write-Verbose "$($_module.name) are not installed, you have not chosen to install missing modules" 334 | } 335 | } 336 | 337 | Write-Output "`n=== \\\ Script Finished! /// ===`n" 338 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![GitHub](https://img.shields.io/github/license/rwidmark/MaintainModule?style=plastic) 2 | ![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/rwidmark/MaintainModule?sort=semver&style=plastic) ![Last release](https://img.shields.io/github/release-date/rwidmark/MaintainModule?style=plastic) 3 | ![GitHub last commit](https://img.shields.io/github/last-commit/rwidmark/MaintainModule?style=plastic) 4 | ![PSGallery downloads](https://img.shields.io/powershellgallery/dt/MaintainModule?style=plastic) 5 | 6 | # MaintainModule 7 | This module let you update all of your installed modules and also uninstall the old versions to keep things clean. 8 | You can also specify module or modules that you want to update. It's also possible to install the module if it's missing and import the modules in the end of the script. 9 | Works on all OS versions. 10 | 11 | ## This module can do the following 12 | - Checks so TLS 1.2 are used by PowerShell 13 | - Making sure that PSGallery are set as trusted 14 | - Update all modules that are installed on the system 15 | - Update specified modules 16 | - Uninstall old versions of the modules 17 | - If specified module are missing you can choose to install it 18 | - Ignore SkipPublisherCheck 19 | - Update / install Pre-release 20 | 21 | ## Dependencies 22 | - Module also require that you have my service module installed, [rsServiceModule](https://github.com/rwidmark/rsServiceModule) 23 | 24 | # Links 25 | * [My PowerShell Collection](https://github.com/rwidmark/PSCollection) 26 | * [Webpage/Blog](https://widmark.dev) 27 | * [X](https://twitter.com/widmark_robin) 28 | * [Mastodon](https://mastodon.social/@rwidmark) 29 | * [YouTube](https://www.youtube.com/@rwidmark) 30 | * [LinkedIn](https://www.linkedin.com/in/rwidmark/) 31 | * [GitHub](https://github.com/rwidmark) 32 | 33 | 34 | ## Notes 35 | The parameter -Scope don't effect the uninstall-module function this is because of limitation from Microsoft. 36 | -Scope effect Install/update module function. 37 | 38 | ## Install 39 | Install for current user 40 | ``` 41 | Install-Module -Name MaintainModule -Scope CurrentUser -Force 42 | ``` 43 | 44 | Install for all users 45 | ``` 46 | Install-Module -Name MaintainModule -Scope AllUsers -Force 47 | ``` 48 | 49 | ## Update-RSModule 50 | ### Update all modules that are installed on the system 51 | You can do that if you run the command. 52 | ```` 53 | Update-RSModule 54 | ```` 55 | You can also use the -Scope parameter if you want to change from CurrentUser to AllUsers, for example ```-Scope "AllUser"``` 56 | If -Scope parameter are empty it will set it as CurrentUser as default. 57 | 58 | ### Update specific module 59 | If you want you can update specific modules, you can do that with the following command. 60 | ```` 61 | Update-RSModule -Module "VMWare.PowerCLI" 62 | ```` 63 | The parameter Module has support for multiple inputs, separate them with , for example ```-Module "ImportExcel", "VMWare.PowerCLI"``` 64 | You can also use the -Scope parameter if you want to change from CurrentUser to AllUsers, for example ```-Scope "AllUser"``` 65 | If -Scope parameter are empty it will set it as CurrentUser as default. 66 | 67 | ### Uninstall old versions of all modules 68 | If you want to uninstall all of the old versions for all of your modules that you have installed 69 | ```` 70 | Update-RSModule -UninstallOldVersion 71 | ```` 72 | You can also use the -Scope parameter if you want to change from CurrentUser to AllUsers, for example ```-Scope "AllUser"``` 73 | If -Scope parameter are empty it will set it as CurrentUser as default. 74 | 75 | 76 | ### Uninstall old versions of a specific module only 77 | If you want to uninstall old versions of only a specific module you can run 78 | ```` 79 | Update-RSModule -Module "ImportExcel" -UninstallOldVersion 80 | ```` 81 | The parameter Module has support for multiple inputs, separate them with , for example ```-Module "ImportExcel", "VMWare.PowerCLI"``` 82 | You can also use the -Scope parameter if you want to change from CurrentUser to AllUsers, for example ```-Scope "AllUser"``` 83 | If -Scope parameter are empty it will set it as CurrentUser as default. 84 | 85 | ### Install missing module or modules 86 | It's possible to install modules if they are not installed on the system, this only works if you have specified module or modules in the Module parameter. 87 | If the module are installed already this will not have any effect and the module will only get updated. 88 | ```` 89 | Update-RSModule -Module "VMWare.PowerCLI" -InstallMissing 90 | ```` 91 | The parameter Module has support for multiple inputs, separate them with , for example ```-Module "ImportExcel", "VMWare.PowerCLI"``` 92 | You can also use the -Scope parameter if you want to change from CurrentUser to AllUsers, for example ```-Scope "AllUser"``` 93 | If -Scope parameter are empty it will set it as CurrentUser as default. 94 | 95 | ### Allow pre-release (only exists in beta) 96 | If you want to allow pre-releases simply add ```-AllowPrerelease $true```` 97 | 98 | ### SkipPublisherCheck (only exists in beta) 99 | If you for some reason want to skip publisher check add ```-SkipPublisherCheck $true``` this is needed for Pester and PowerCLI for an example -------------------------------------------------------------------------------- /publish.ps1: -------------------------------------------------------------------------------- 1 | $ModulePath = "$PSScriptRoot\MaintainModule" 2 | Publish-Module -Path $ModulePath -NuGetApiKey $Env:PSGALLERY -------------------------------------------------------------------------------- /test/PSScriptAnalyzer_MaintainModule.psd1_2023-01-19.md: -------------------------------------------------------------------------------- 1 | 0 rule violations found. 2 | -------------------------------------------------------------------------------- /test/PSScriptAnalyzer_MaintainModule.psm1_2023-01-19.md: -------------------------------------------------------------------------------- 1 | 0 rule violations found. 2 | -------------------------------------------------------------------------------- /test/PSScriptAnalyzer_Uninstall-RSModule_2023-01-19.md: -------------------------------------------------------------------------------- 1 | 0 rule violations found. 2 | -------------------------------------------------------------------------------- /test/PSScriptAnalyzer_Update-RSModule_2023-01-19.md: -------------------------------------------------------------------------------- 1 | 0 rule violations found. 2 | --------------------------------------------------------------------------------