Public/Update-Office365Modules.ps1
|
function Update-Office365Modules { param ( [switch]$AllowPrerelease, [switch]$Refresh ) $local:Functions= Get-Office365ModuleInfo $local:UsePre = if ($AllowPrerelease.IsPresent) { $true } else { [bool]$script:myOffice365Services['AllowPrerelease'] } if ($Refresh) { $script:myOffice365Services['OnlineVersionCache'].Clear() } $local:IsAdmin= Test-IsAdministrator If( $local:IsAdmin) { If( (Get-Process -Name powershell, pwsh -ErrorAction SilentlyContinue | Measure-Object).Count -gt 1) { Write-Host ('Running multiple PowerShell sessions, successful updating might be problematic.') -ForegroundColor $script:myConsoleColors.Warning } } $local:ProgramFilesPath= [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::ProgramFiles) # Pre-fetch all online versions in parallel (PS 7+) to avoid N sequential network calls # in the loop below. Cache is shared with Show-Office365Modules (60-min TTL). if ($PSVersionTable.PSVersion.Major -ge 7) { $local:UsePSRG = $script:myOffice365Services['PSResourceGet'] $local:ToFetch = $local:Functions.Module | Where-Object { $local:e = $script:myOffice365Services['OnlineVersionCache'][$_] $null -eq $local:e -or ([datetime]::Now - $local:e.Fetched).TotalMinutes -ge 60 } if ($local:ToFetch) { $local:ToFetch | ForEach-Object -Parallel { $local:n = $_ $local:o = if ($using:UsePSRG) { Find-PSResource -Name $local:n -Prerelease:$using:UsePre -ErrorAction SilentlyContinue } else { Find-Module -Name $local:n -AllowPrerelease:$using:UsePre -ErrorAction SilentlyContinue } [PSCustomObject]@{ Name=$local:n; Version=if($local:o){[string]$local:o.Version}else{$null} } } -ThrottleLimit 10 | ForEach-Object { $script:myOffice365Services['OnlineVersionCache'][$_.Name] = [PSCustomObject]@{ Version = $_.Version; Fetched = [datetime]::Now } } } } $local:AllInstalled = Get-Module -ListAvailable -ErrorAction SilentlyContinue ForEach ( $local:Item in $local:Functions) { $local:Module= Get-InstalledRepoModule -Name $local:Item.Module -Repo $local:Item.Repo -AllInstalled $local:AllInstalled If( ($local:Module).RepositorySourceLocation) { If( -not $local:IsAdmin -and ($local:Module.ModuleBase -like "$local:ProgramFilesPath*")) { Write-Host ('{0}: Skipped (installed in AllUsers scope; re-run as administrator to update)' -f $local:Item.Description) -ForegroundColor $script:myConsoleColors.Warning Continue } $local:ModuleScope = if ($local:Module.ModuleBase -like "$local:ProgramFilesPath*") { 'AllUsers' } else { 'CurrentUser' } $local:Version = Get-ModuleVersionInfo -Module $local:Module Write-Host ('Checking {0}' -f $local:Item.Description) -NoNewLine $local:NewerAvailable= $false $local:OnlineVer = Get-OnlineModuleVersion -Name $local:Item.Module If( $local:OnlineVer) { Write-Host (' v{0} (Online v{1})' -f $local:Version, $local:OnlineVer) -NoNewline If( (Compare-TextVersionNumber -Version $local:Version -CompareTo $local:OnlineVer) -eq 1) { Write-Host (' Update available') -ForegroundColor $script:myconsoleColors.Error $local:NewerAvailable= $true } Else{ Write-Host '' } } Else { # Not installed from online or cannot determine Write-Host (' v{0} (Online N/A)' -f $local:Version) -ForegroundColor $script:myconsoleColors.Warning } If( $local:NewerAvailable) { $local:UpdateSuccess= $false Try { Update-myModule -Name $local:Item.Module -Scope $local:ModuleScope $local:UpdateSuccess= $true } Catch { Write-Host ('Problem updating {0}: {1}' -f $local:Item.Module, $_.Exception.Message) -ForegroundColor $script:myConsoleColors.Error } If( $local:UpdateSuccess) { Write-Host ('Updated {0} to version {1}' -f $local:Item.Description, $local:OnlineVer) -ForegroundColor $script:myConsoleColors.OK # Uninstall all older versions; use OnlineVer as the new baseline so we # correctly identify old versions regardless of which package manager ran. $local:ModuleVersions= Get-Module -Name $local:Item.Module -ListAvailable -ErrorAction SilentlyContinue | Where-Object { $_.RepositorySourceLocation -and ([System.Uri]($_.RepositorySourceLocation)).Authority -ieq ([System.Uri]($local:Item.Repo)).Authority } $local:LatestVersion = $local:OnlineVer # Uninstall all old versions of module & dependencies If( $local:OnlineVer) { ForEach( $DependencyModule in $Module.Dependencies) { $local:DepModuleVersions= Get-myModule -Name $DependencyModule.Name -ListAvailable $local:DepModule = $local:DepModuleVersions | Sort-Object -Property @{e={ [System.Version]($_.Version -replace '[^\d\.]','')}} -Descending | Select-Object -First 1 $local:DepLatestVersion = ($local:DepModule).Version $local:OldDepModules= $local:DepModuleVersions | Where-Object {$_.Version -ne $local:DepLatestVersion} $local:OldDepModules | ForEach-Object { $DepModule= $_ Write-Host ('Uninstalling dependency {0} version {1}' -f $DepModule.Name, $DepModule.Version) Try { Uninstall-myModule -Name $DepModule.Name -Version $DepModule.Version -IsPrerelease:$DepModule.IsPrerelease } Catch { Write-Warning ('Problem uninstalling {0} v{1}: {2}' -f $DepModule.Name, $DepModule.Version, $_.Exception.Message) } } } $local:OldModules= $local:ModuleVersions | Where-Object {$_.Version -ne $local:LatestVersion} If( $local:OldModules) { ForEach( $OldModule in $local:OldModules) { Write-Host ('Uninstalling {0} version {1}' -f $local:Item.Description, $OldModule.Version) Try { Uninstall-myModule -Name $OldModule.Name -Version $OldModule.Version -IsPrerelease:$OldModule.IsPrerelease } Catch { Write-Warning ('Problem uninstalling {0} v{1}: {2}' -f $OldModule.Name, $OldModule.Version, $_.Exception.Message) } } } } } Else { # Problem during update } } Else { # No update available } } Else { # Not installed } } } |