Public/Sync-OSDAppTeams.ps1
|
function Sync-OSDAppTeams { [CmdletBinding(SupportsShouldProcess)] param( [ValidateSet('x86','x64','arm64')] [string]$Architecture = 'x64', [double]$MinimumFreeSpaceGB = 2, [string]$BootstrapperUri = 'https://go.microsoft.com/fwlink/?clcid=0x409&linkid=2243204' ) if (Test-OSDAppWinPE) { throw 'Sync-OSDAppTeams is intended for full Windows. Built-in cache refresh is deferred until the pre-install phase.' } $cachePath = Get-OSDAppCachePath $clientLogPath = Join-Path $cachePath 'Logs\Client.log' $root = Join-Path $cachePath 'BuiltIn\Teams' $bootstrapperPath = Join-Path $root 'teamsbootstrapper.exe' $msixPath = Join-Path $root 'teams.msix' $cacheInfoPath = Join-Path $root 'CacheInfo.json' New-Item -ItemType Directory -Path $root -Force | Out-Null $resolvedArchitecture = $Architecture $msixUri = switch ($resolvedArchitecture) { 'x86' { 'https://go.microsoft.com/fwlink/?clcid=0x409&linkid=2196060' } 'x64' { 'https://go.microsoft.com/fwlink/?linkid=2196106' } 'arm64' { 'https://go.microsoft.com/fwlink/?clcid=0x409&linkid=2196207' } } if (-not $PSCmdlet.ShouldProcess($root, "Configure and synchronize Microsoft Teams built-in cache ($resolvedArchitecture)")) { return } Assert-OSDAppCacheFreeSpace -CachePath $cachePath -MinimumFreeSpaceGB $MinimumFreeSpaceGB -Operation 'Microsoft Teams cache synchronization' -LogPath $clientLogPath | Out-Null Write-OSDAppLog -LogPath $clientLogPath -Component 'Teams' -Event 'BuiltInSyncStart' -Message 'Synchronizing Microsoft Teams built-in cache.' -Data @{ Architecture = $resolvedArchitecture } Write-Progress -Id 10 -Activity 'Synchronizing Microsoft Teams cache' -Status 'Checking current Microsoft package metadata...' -PercentComplete 5 $remoteMetadata = Get-OSDAppRemoteFileMetadata -Uri $msixUri $previousCacheInfo = $null if (Test-Path -LiteralPath $cacheInfoPath -PathType Leaf) { try { $previousCacheInfo = Get-Content -LiteralPath $cacheInfoPath -Raw -Encoding UTF8 | ConvertFrom-Json } catch { } } $metadataMatches = $false if ((Test-Path -LiteralPath $msixPath -PathType Leaf) -and $previousCacheInfo) { if ($remoteMetadata.ETag -and $previousCacheInfo.RemoteETag) { $metadataMatches = $remoteMetadata.ETag -eq $previousCacheInfo.RemoteETag } elseif ($remoteMetadata.LastModified -and $previousCacheInfo.RemoteLastModified -and $remoteMetadata.ContentLength -and $previousCacheInfo.RemoteContentLength) { $metadataMatches = ($remoteMetadata.LastModified -eq $previousCacheInfo.RemoteLastModified -and [int64]$remoteMetadata.ContentLength -eq [int64]$previousCacheInfo.RemoteContentLength) } } Write-Progress -Id 10 -Activity 'Synchronizing Microsoft Teams cache' -Status 'Downloading bootstrapper...' -PercentComplete 10 Save-OSDAppDownload -Uri $BootstrapperUri -DestinationPath $bootstrapperPath -Activity 'Downloading Microsoft Teams bootstrapper' -ProgressId 11 -ParentProgressId 10 | Out-Null if ($metadataMatches) { $resolvedVersion = [string]$previousCacheInfo.Version $updated = $false Write-Progress -Id 10 -Activity 'Synchronizing Microsoft Teams cache' -Status "Cached Teams $resolvedVersion is current. No MSIX download required." -PercentComplete 90 } else { Write-Progress -Id 10 -Activity 'Synchronizing Microsoft Teams cache' -Status 'Downloading Teams MSIX...' -PercentComplete 15 Save-OSDAppDownload -Uri $msixUri -DestinationPath $msixPath -Activity "Downloading Microsoft Teams $resolvedArchitecture MSIX" -ProgressId 12 -ParentProgressId 10 | Out-Null Write-Progress -Id 10 -Activity 'Synchronizing Microsoft Teams cache' -Status 'Reading MSIX package metadata...' -PercentComplete 85 $metadataStopwatch = [System.Diagnostics.Stopwatch]::StartNew() Write-OSDAppLog -LogPath $clientLogPath -Component 'Teams' -Event 'MsixMetadataReadStart' -Message 'Reading Teams MSIX package metadata.' -Data @{ Path = $msixPath } Add-Type -AssemblyName System.IO.Compression.FileSystem -ErrorAction SilentlyContinue $archive = [System.IO.Compression.ZipFile]::OpenRead($msixPath) try { $manifestEntry = $archive.Entries | Where-Object { $_.FullName -eq 'AppxManifest.xml' } | Select-Object -First 1 if (-not $manifestEntry) { throw 'AppxManifest.xml was not found in the downloaded Teams MSIX.' } $reader = New-Object System.IO.StreamReader($manifestEntry.Open()) try { [xml]$appxManifest = $reader.ReadToEnd() } finally { $reader.Dispose() } $resolvedVersion = [string]$appxManifest.Package.Identity.Version } finally { $archive.Dispose() } $metadataStopwatch.Stop() Write-OSDAppLog -LogPath $clientLogPath -Component 'Teams' -Event 'MsixMetadataReadComplete' -Message 'Teams MSIX package metadata read completed.' -Data @{ Version = $resolvedVersion; DurationMs = $metadataStopwatch.ElapsedMilliseconds } $updated = $true } Write-Progress -Id 10 -Activity 'Synchronizing Microsoft Teams cache' -Status 'Updating cache metadata...' -PercentComplete 95 [ordered]@{ Id='Teams'; Cached=$true; Version=$resolvedVersion; Architecture=$resolvedArchitecture; SourcePolicy='Evergreen'; SyncMethod='HttpMetadata'; Updated=$updated; BootstrapperUri=$BootstrapperUri; RemoteETag=$remoteMetadata.ETag; RemoteLastModified=$remoteMetadata.LastModified; RemoteContentLength=$remoteMetadata.ContentLength; RemoteFinalUri=$remoteMetadata.FinalUri; SyncedAt=(Get-Date).ToUniversalTime().ToString('o') } | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath $cacheInfoPath -Encoding UTF8 Write-OSDAppLog -LogPath $clientLogPath -Component 'Teams' -Event 'BuiltInSyncComplete' -Message 'Microsoft Teams built-in cache synchronized.' -Data @{ Version=$resolvedVersion; Architecture=$resolvedArchitecture; Updated=$updated; Path=$root; SourcePolicy='Evergreen'; SyncMethod='HttpMetadata' } Write-Progress -Id 10 -Activity 'Synchronizing Microsoft Teams cache' -Status 'Completed.' -PercentComplete 100 Start-Sleep -Milliseconds 350 Write-Progress -Id 10 -Activity 'Synchronizing Microsoft Teams cache' -Completed [pscustomobject]@{ PSTypeName='OSDApps.BuiltInCache'; Id='Teams'; Version=$resolvedVersion; Architecture=$resolvedArchitecture; CachePath=$root; Cached=$true; Updated=$updated } } |