Forum Discussion
Backgrounds
I've created a powershell script to convert a directory of image files to png, create both an original and thumbnail image with the correct guid and filename. I was then able to see the files in the new teams.
# Install the necessary .NET namespace
Add-Type -AssemblyName System.Drawing
# Import the necessary .NET namespace
Add-Type -AssemblyName System.Drawing
# Dummy function to satisfy the GetThumbnailImage method
function dummyCallback { return $false }
# Define the folder containing the image files
$sourceFolder = "C:\Path\To\Source\Images"
# Define the folder to save the converted images
$destinationFolder = "C:\Path\To\Destination"
# Loop through each image file in the source folder
Get-ChildItem -Path $sourceFolder -File | ForEach-Object {
# Generate a GUID for the new image name
$guid = [guid]::NewGuid().ToString()
# Create a .NET Bitmap object from the image file
$originalImage = [System.Drawing.Image]::FromFile($_.FullName)
# Save the image as a PNG with a GUID-based name
$originalImage.Save("$destinationFolder\$guid.png", [System.Drawing.Imaging.ImageFormat]::Png)
# Create a thumbnail image
$thumbWidth = 278
$thumbHeight = 159
$thumbnailImage = $originalImage.GetThumbnailImage($thumbWidth, $thumbHeight, [System.Drawing.Image+GetThumbnailImageAbort]$dummyCallback, [System.IntPtr]::Zero)
# Save the thumbnail image as a PNG with a GUID-based name and "_thumb" suffix
$thumbnailImage.Save("$destinationFolder\$guid`_thumb.png", [System.Drawing.Imaging.ImageFormat]::Png)
# Dispose of the image objects to free resources
$originalImage.Dispose()
$thumbnailImage.Dispose()
}
- Steve_PrenticeSep 05, 2023Iron ContributorI love this, well done and thanks.
I'm trying to get my head around how I could store images centrally and get clients to check on a scheduled bases for newly added images... for now this script is great as a run once, but the random GUIDs mean it can't be run multiple times. I guess the only way around that is some sort of local log file that the script updates/checks against which has the original image name and the GUID that was produced, and if either doesn't exist then carry on, otherwise skip.
Anyone else any better ideas?- brzayasSep 05, 2023Copper Contributor
Steve_Prentice So I'm not hosting these images in an Azure blob. What I implemented in my environment was deploying this as an Intune Win32 App and using PowerShell scripts to Install, Uninstall and Detect the correct files are placed in both the Old Teams Background directory and the New Teams. Since our org are still on a mix of both app variants. As far as wanting to update images, what you can do is when their are new images you can just create a new Intune App with the new photos whenever you have new images to upload. The GUID is a unique identifier so different images won't have the same GUID.
If anyone would like to go that route, below is what I setup.
- I have a directory with the install/uninstall/detection Scripts and a folder called bg that contains all the background images, you can place as many as you want.
- Using the IntuneWinAppUtil.exe I package all the files for creating the app on Intune
- When creating the app I used these Install/Uninstall commands
- Install:
%SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -command .\install.ps1 - Uninstall:
%SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -command .\uninstall.ps1
- Install:
Below are the scripts for this app:
install.ps1
$PackageName = "Teams-Backgrounds" $Version = "1" $Path_4Log = "$ENV:LOCALAPPDATA\_MEM" Start-Transcript -Path "$Path_4Log\Log\$PackageName-install.log" -Force $ErrorActionPreference = "Stop" try{ # Local folder $TeamsBG_Folder = "$env:APPDATA\Microsoft\Teams\Backgrounds\Uploads" $TeamsBG_Folder_New = "$env:LOCALAPPDATA\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\Backgrounds\Uploads" # Ensure the folder is present New-Item -ItemType directory -Path $TeamsBG_Folder -Force # Copy backgrounds New-Item -ItemType directory -Path $TeamsBG_Folder_New -Force Copy-Item -path ".\bg\*" -Destination $TeamsBG_Folder_New -Recurse -Force Copy-Item -path '.\bg\*' -Destination $TeamsBG_Folder -Recurse -Force # Validation File New-Item -Path "$Path_4Log\Validation\$PackageName" -ItemType "file" -Value $Version -Force }catch{ Write-Host "_____________________________________________________________________" Write-Host "ERROR" Write-Host "$_" Write-Host "_____________________________________________________________________" } Stop-Transcriptuninstall.ps1
$PackageName = "Teams-Backgrounds" $Path_4Log = "$ENV:LOCALAPPDATA\_MEM" Start-Transcript -Path "$Path_4Log\Log\$PackageName-uninstall.log" -Force $TeamsBG_Folder = "$env:APPDATA\Microsoft\Teams\Backgrounds\Uploads" $TeamsBG_Folder_New = "$env:LOCALAPPDATA\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\Backgrounds\Uploads" $TeamsBG_Files = Get-ChildItem -Path '.\bg' -Name # Delete distributed backgrounds Get-ChildItem $TeamsBG_Folder_New | Where{$_.Name -in $TeamsBG_Files} | Remove-Item Get-ChildItem $TeamsBG_Folder | Where{$_.Name -in $TeamsBG_Files} | Remove-Item # Delete detection file Remove-Item -Path "$Path_4Log\Validation\$PackageName" -Force Stop-Transcriptcheck.ps1
$PackageName = "Teams-Backgrounds" $Version = "1" $Path_4Log = "$ENV:LOCALAPPDATA\_MEM" $ProgramVersion_current = Get-Content -Path "$Path_4Log\Validation\$PackageName" if($ProgramVersion_current -eq $Version){ Write-Host "Found it!" }I hope this helps anyone looking for an alternative way to deploy teams backgrounds.
- _c4os_Sep 08, 2023Copper Contributor
Like everything in IT, many solutions are available. Here's mine in case it's of any help for someone else.
What it does:
Download images from Azure Blob directly to New Teams Upload folder
How it does:
checks for New Teams to be installed and for Blob URL to be reacheable
Creates "Upload" folder if doesn't exist and bittransfer all files contained in a Blob folder into New Teams user folder using Intune Win32 app deploy
How it checks:
Detection is a dynamic script which check for each file in Azure Blob folder to exist in New Teams folder. If one or more files are missing, it will trigger a new deploy therefore Azure Blob folder can have pictures removed or added and it will dynamically reflects on clients devices
It's a Win32 app that needs to be packed with intunewinapputil
Main Script:
# hide windows terminal console # https://stackoverflow.com/questions/74968665/hide-the-windows-terminal-console-window-with-powershell function Hide-ConsoleWindow() { $ShowWindowAsyncCode = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);' $ShowWindowAsync = Add-Type -MemberDefinition $ShowWindowAsyncCode -name Win32ShowWindowAsync -namespace Win32Functions -PassThru $hwnd = (Get-Process -PID $pid).MainWindowHandle if ($hwnd -ne [System.IntPtr]::Zero) { # When you got HWND of the console window: # (It would appear that Windows Console Host is the default terminal application) $ShowWindowAsync::ShowWindowAsync($hwnd, 0) } else { # When you failed to get HWND of the console window: # (It would appear that Windows Terminal is the default terminal application) # Mark the current console window with a unique string. $UniqueWindowTitle = New-Guid $Host.UI.RawUI.WindowTitle = $UniqueWindowTitle $StringBuilder = New-Object System.Text.StringBuilder 1024 # Search the process that has the window title generated above. $TerminalProcess = (Get-Process | Where-Object { $_.MainWindowTitle -eq $UniqueWindowTitle }) # Get the window handle of the terminal process. # Note that GetConsoleWindow() in Win32 API returns the HWND of # powershell.exe itself rather than the terminal process. # When you call ShowWindowAsync(HWND, 0) with the HWND from GetConsoleWindow(), # the Windows Terminal window will be just minimized rather than hidden. $hwnd = $TerminalProcess.MainWindowHandle if ($hwnd -ne [System.IntPtr]::Zero) { $ShowWindowAsync::ShowWindowAsync($hwnd, 0) } else { Write-Host "Failed to hide the console window." } } } Hide-ConsoleWindow ## Set variables $name = "NewTeams_backgrounds" $ver = "1.0" $type = "APP" $logname = "$type-$name.log" $logPath = "$env:ProgramData\Microsoft\IntuneManagementExtension\Logs\" $LogFile = Join-Path $logPath $logname # Checking permissions Write-Output "checking permissions on $logPath" $acl = Get-Acl -Path $logPath $aclcheck = $acl.Access | Where-Object { $_.IsInherited -eq $false -and $_.FileSystemRights -match 'Modify'} if ($null -eq $aclcheck) { try { # Changing permissions to Logs folder Write-Output "adding Modify permissions on builtin\users group" $rights = 'Modify' $inheritance = 'ContainerInherit, ObjectInherit' $propagation = 'None' $type = 'Allow' $SID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-545") $ACE = New-Object System.Security.AccessControl.FileSystemAccessRule($SID, $rights, $inheritance, $propagation, $type) $acl = Get-Acl -Path $logPath $acl.SetAccessRule($ACE) $acl | Set-Acl -Path $logPath Write-Output "permissions modified on $logPath" } catch { Write-Output "Error setting up permissions for $logPath. The error is below:" Write-Output $_ } } Write-Output "permissions are fine" # Function to write log entries function Write-Log { param( [string]$Message ) $Timestamp = Get-Date -Format "dd-MM-yyyy HH:mm:ss" $LogEntry = "$Timestamp - $Message" $LogEntry | Out-File -FilePath $LogFile -Append } # Main script try { Write-Log "Installing $name version $ver" Write-Log "checking New Teams folders" $NewTeams_background = "$env:LOCALAPPDATA\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\Backgrounds" $NewTeams_Uploads = "$env:LOCALAPPDATA\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\Backgrounds\Uploads" if (!(Test-Path -path $NewTeams_background)) { Write-Log "creating folder $NewTeams_background" New-Item $NewTeams_background -itemtype directory -force}; if (!(Test-Path -path $NewTeams_Uploads)) { Write-Log "creating folder $NewTeams_Uploads" New-Item $NewTeams_Uploads -itemtype directory -force}; $URL = "YOUR_BLOB_URL_WITH_SAS" $uri = "https://yourcompanyblobname.blob.core.windows.net/yourcompanyfolder/NewTeams_Background" $body = Invoke-RestMethod -uri $URL $xml = [xml]$body.Substring($body.IndexOf('<')) $files = $xml.ChildNodes.Blobs.Blob.Name | where-Object {$_ -like "NewTeams_Background/*"} $files = $files -replace "NewTeams_Background/","" Write-Log "following files are on Azure Blob: $files" $files | ForEach-Object { $downloadpath = $NewTeams_Uploads + "/" + $_ if (!(Test-Path -Path $downloadpath)){ $URL = "$($uri)/$_" Write-Log "Downloading $_" #Invoke-WebRequest -Uri $URL -OutFile "$NewTeams_Uploads\$_" -TimeoutSec 30 -UseBasicParsing:$true -ErrorAction SilentlyContinue Start-BitsTransfer -Source $URL -Destination "$NewTeams_Uploads\$_" -Priority Normal -ErrorAction SilentlyContinue } } Write-Log "Installation of $name completed" } catch { Write-Log "Error running $name install. The error is below:" Write-Log $_ }you'd need to change $uri and $URL accordingly
Pictures need to be uploaded into $uri location
It has a function to hide the powershell and terminal window since it's installed under User environment
It saves log into the default Intune log folder and since it runs as user, it checks for log folder correct permissions
Detection script:
$NewTeams_Uploads = "$env:LOCALAPPDATA\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\Backgrounds\Uploads" $URL = "YOUR_COMPANY_BLOB_URL_WITH_SAS" $missing = 0 $body = Invoke-RestMethod -uri $URL $xml = [xml]$body.Substring($body.IndexOf('<')) $files = $xml.ChildNodes.Blobs.Blob.Name | where-Object {$_ -like "NewTeams_Background/*"} $files = $files -replace "NewTeams_Background/","" $files | ForEach-Object { $download_path = $NewTeams_Uploads + "/" + $_ if (!(Test-Path -Path $download_path)){ $missing++ } } if ($missing -eq "0"){ Write-Host "New Teams backgrounds pictures installed" }Then you have simple requirements script, one for Blob URL to be reacheable:
$url = "YOUR_COMPANY_BLOB_URL_WITH_SAS" $client = New-Object System.Net.WebClient $client.DownloadString($url) | Out-Null Write-Host "The URL is reachable"and one for New Teams folder to exist (to be checked with logged on credentials):
# runs with logged on creds $NewTeams_path = "$env:LOCALAPPDATA\Packages\MSTeams_8wekyb3d8bbwe" if (Test-Path $NewTeams_path) { Write-Host "New Teams installed" }Enjoy
- I have a directory with the install/uninstall/detection Scripts and a folder called bg that contains all the background images, you can place as many as you want.