Last active
March 20, 2026 00:47
-
-
Save skarllot/d7732d0cb87268967bb038af717fb122 to your computer and use it in GitHub Desktop.
Sets the profile picture for a Microsoft Edge profile - irm https://tinyurl.com/Set-EdgeProfileImage | iex
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .SYNOPSIS | |
| Sets the profile picture for a Microsoft Edge profile. | |
| .DESCRIPTION | |
| This script replaces the profile picture (Edge Profile Picture.png) for a chosen | |
| Edge profile, including resizing the image to 424x424 px and updating the | |
| Local State JSON so Edge renders the new picture. | |
| The script: | |
| - Checks if Edge is running (exits if it is) | |
| - Prompts for the source image path | |
| - Lists all Edge profiles and prompts for selection | |
| - Creates automatic backups in your home directory | |
| - Resizes the source image to 424x424 using high-quality bicubic interpolation | |
| - Copies the resized image as the profile picture | |
| - Updates Local State: use_gaia_picture, is_using_new_placeholder_avatar_icon, | |
| gaia_picture_file_name | |
| - Provides rollback instructions if needed | |
| .EXAMPLE | |
| .\Set-EdgeProfileImage.ps1 | |
| Runs the script fully interactively, prompting for the image path and profile. | |
| .NOTES | |
| Version: 1.1 | |
| IMPORTANT: Close Microsoft Edge completely before running this script. | |
| Backups are created automatically in: $env:USERPROFILE\EdgeProfileImageBackup_[timestamp]\ | |
| #> | |
| [CmdletBinding()] | |
| param() | |
| $ErrorActionPreference = 'Stop' | |
| #region Helper Functions | |
| function Write-ColorMessage { | |
| param( | |
| [string]$Message, | |
| [ValidateSet('Success','Error','Info','Warning')] | |
| [string]$Type = 'Info' | |
| ) | |
| $color = switch ($Type) { | |
| 'Success' { 'Green' } | |
| 'Error' { 'Red' } | |
| 'Warning' { 'Yellow' } | |
| 'Info' { 'Cyan' } | |
| } | |
| Write-Host $Message -ForegroundColor $color | |
| } | |
| function Test-EdgeRunning { | |
| $edgeProcesses = Get-Process -Name 'msedge' -ErrorAction SilentlyContinue | |
| return ($null -ne $edgeProcesses) | |
| } | |
| function Get-EdgeUserDataPath { | |
| return "$env:LOCALAPPDATA\Microsoft\Edge\User Data" | |
| } | |
| function Get-EdgeProfiles { | |
| $userDataPath = Get-EdgeUserDataPath | |
| $localStatePath = Join-Path $userDataPath 'Local State' | |
| if (-not (Test-Path $localStatePath)) { | |
| throw "Edge Local State file not found at: $localStatePath" | |
| } | |
| $utf8 = [System.Text.UTF8Encoding]::new($false) | |
| $localState = [System.IO.File]::ReadAllText($localStatePath, $utf8) | ConvertFrom-Json | |
| $profiles = @() | |
| foreach ($profileKey in $localState.profile.info_cache.PSObject.Properties.Name) { | |
| $profileData = $localState.profile.info_cache.$profileKey | |
| $picturePath = Join-Path $userDataPath "$profileKey\Edge Profile Picture.png" | |
| $hasPicture = Test-Path $picturePath | |
| $profiles += [PSCustomObject]@{ | |
| Key = $profileKey | |
| Name = $profileData.name | |
| AccountEmail = $profileData.user_name | |
| HasPicture = $hasPicture | |
| } | |
| } | |
| return $profiles | |
| } | |
| function Show-ProfileList { | |
| param([array]$Profiles) | |
| Write-ColorMessage "`nAvailable Edge Profiles:" -Type Info | |
| Write-Host ("=" * 80) | |
| for ($i = 0; $i -lt $Profiles.Count; $i++) { | |
| $profile = $Profiles[$i] | |
| $pictureStatus = if ($profile.HasPicture) { '[Has Picture]' } else { '[No Picture]' } | |
| $pictureColor = if ($profile.HasPicture) { 'Green' } else { 'Gray' } | |
| Write-Host ("{0,3}. " -f ($i + 1)) -NoNewline | |
| Write-Host ("{0,-20} " -f $profile.Key) -NoNewline -ForegroundColor White | |
| Write-Host ("{0,-25} " -f $profile.Name) -NoNewline | |
| Write-Host ("{0,-15}" -f $pictureStatus) -ForegroundColor $pictureColor | |
| if ($profile.AccountEmail) { | |
| Write-Host (" Account: {0}" -f $profile.AccountEmail) -ForegroundColor Gray | |
| } | |
| } | |
| Write-Host ("=" * 80) | |
| } | |
| function New-BackupDirectory { | |
| $timestamp = Get-Date -Format 'yyyyMMdd_HHmmss' | |
| $backupPath = Join-Path $env:USERPROFILE "EdgeProfileImageBackup_$timestamp" | |
| if (-not (Test-Path $backupPath)) { | |
| New-Item -ItemType Directory -Path $backupPath -Force | Out-Null | |
| } | |
| return $backupPath | |
| } | |
| function Backup-ProfileFiles { | |
| param( | |
| [string]$ProfileKey, | |
| [string]$BackupPath | |
| ) | |
| $userDataPath = Get-EdgeUserDataPath | |
| # Backup Local State | |
| $localStatePath = Join-Path $userDataPath 'Local State' | |
| $localStateBackup = Join-Path $BackupPath 'Local State' | |
| Copy-Item $localStatePath $localStateBackup -Force | |
| Write-ColorMessage " [✓] Backed up: Local State" -Type Success | |
| # Backup existing profile picture (if present) | |
| $picturePath = Join-Path $userDataPath "$ProfileKey\Edge Profile Picture.png" | |
| if (Test-Path $picturePath) { | |
| $profileBackupDir = Join-Path $BackupPath $ProfileKey | |
| New-Item -ItemType Directory -Path $profileBackupDir -Force | Out-Null | |
| $pictureBackup = Join-Path $profileBackupDir 'Edge Profile Picture.png' | |
| Copy-Item $picturePath $pictureBackup -Force | |
| Write-ColorMessage " [✓] Backed up: $ProfileKey\Edge Profile Picture.png" -Type Success | |
| } | |
| return $true | |
| } | |
| function Invoke-ImageResize { | |
| param( | |
| [string]$SourcePath, | |
| [string]$DestPath | |
| ) | |
| Add-Type -AssemblyName 'System.Drawing' | |
| $src = $null | |
| $dst = $null | |
| $g = $null | |
| try { | |
| $src = [System.Drawing.Bitmap]::new($SourcePath) | |
| $dst = [System.Drawing.Bitmap]::new(424, 424) | |
| $g = [System.Drawing.Graphics]::FromImage($dst) | |
| $g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic | |
| $g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality | |
| $g.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality | |
| $g.DrawImage($src, 0, 0, 424, 424) | |
| $dst.Save($DestPath, [System.Drawing.Imaging.ImageFormat]::Png) | |
| Write-ColorMessage " [✓] Image resized to 424x424 px" -Type Success | |
| } catch { | |
| Write-ColorMessage " [!] Resize failed ($($_.Exception.Message)); copying original instead" -Type Warning | |
| Copy-Item $SourcePath $DestPath -Force | |
| } finally { | |
| if ($g) { $g.Dispose() } | |
| if ($dst) { $dst.Dispose() } | |
| if ($src) { $src.Dispose() } | |
| } | |
| } | |
| function Set-ProfilePicture { | |
| param( | |
| [string]$ProfileKey, | |
| [string]$ResizedImagePath | |
| ) | |
| $userDataPath = Get-EdgeUserDataPath | |
| $localStatePath = Join-Path $userDataPath 'Local State' | |
| $destPicture = Join-Path $userDataPath "$ProfileKey\Edge Profile Picture.png" | |
| # Copy resized image to profile directory | |
| Copy-Item $ResizedImagePath $destPicture -Force | |
| Write-ColorMessage " [✓] Profile picture written to: $destPicture" -Type Success | |
| # Update Local State (UTF-8 no-BOM to preserve Unicode characters) | |
| $utf8 = [System.Text.UTF8Encoding]::new($false) | |
| $json = [System.IO.File]::ReadAllText($localStatePath, $utf8) | ConvertFrom-Json | |
| $entry = $json.profile.info_cache.$ProfileKey | |
| $entry.use_gaia_picture = $true | |
| $entry.is_using_new_placeholder_avatar_icon = $false | |
| if (-not ($entry.PSObject.Properties.Name -contains 'gaia_picture_file_name')) { | |
| $entry | Add-Member -MemberType NoteProperty -Name 'gaia_picture_file_name' -Value 'Edge Profile Picture.png' | |
| } else { | |
| $entry.gaia_picture_file_name = 'Edge Profile Picture.png' | |
| } | |
| [System.IO.File]::WriteAllText($localStatePath, ($json | ConvertTo-Json -Depth 100 -Compress), $utf8) | |
| Write-ColorMessage " [✓] Local State updated (use_gaia_picture, gaia_picture_file_name)" -Type Success | |
| } | |
| function Show-RollbackInstructions { | |
| param( | |
| [string]$BackupPath, | |
| [string]$ProfileKey | |
| ) | |
| Write-Host "`n" | |
| Write-ColorMessage "=== ROLLBACK INSTRUCTIONS ===" -Type Warning | |
| Write-Host "If you need to undo these changes, run the following commands in PowerShell:" | |
| Write-Host "" | |
| Write-Host " `$backupPath = '$BackupPath'" -ForegroundColor Gray | |
| Write-Host " `$userDataPath = '$(Get-EdgeUserDataPath)'" -ForegroundColor Gray | |
| Write-Host "" | |
| Write-Host " # Close Edge first, then restore:" -ForegroundColor Gray | |
| Write-Host " Copy-Item (Join-Path `$backupPath 'Local State') `$userDataPath -Force" -ForegroundColor Cyan | |
| Write-Host " `$picBackup = Join-Path `$backupPath '$ProfileKey\Edge Profile Picture.png'" -ForegroundColor Cyan | |
| Write-Host " if (Test-Path `$picBackup) { Copy-Item `$picBackup (Join-Path `$userDataPath '$ProfileKey') -Force }" -ForegroundColor Cyan | |
| Write-Host "" | |
| } | |
| #endregion | |
| #region Main Script | |
| try { | |
| Write-Host "`n" | |
| Write-ColorMessage "╔═══════════════════════════════════════════════════════════════╗" -Type Info | |
| Write-ColorMessage "║ Edge Profile Image Setter ║" -Type Info | |
| Write-ColorMessage "╚═══════════════════════════════════════════════════════════════╝" -Type Info | |
| Write-Host "`n" | |
| # Step 1: Prompt for source image path | |
| Write-ColorMessage "[1/7] Source Image" -Type Info | |
| Write-Host "Enter the path to the image file (PNG, JPEG, BMP, GIF, or TIFF): " -NoNewline -ForegroundColor Yellow | |
| $ImagePath = Read-Host | |
| if ([string]::IsNullOrWhiteSpace($ImagePath)) { | |
| Write-ColorMessage "[ERROR] No image path provided." -Type Error | |
| exit 1 | |
| } | |
| # Strip surrounding quotes the user may have pasted from Explorer | |
| $ImagePath = $ImagePath.Trim('"').Trim("'") | |
| if (-not (Test-Path $ImagePath)) { | |
| Write-ColorMessage "[ERROR] Source image not found: $ImagePath" -Type Error | |
| exit 1 | |
| } | |
| $validExtensions = @('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.tiff', '.tif') | |
| $ext = [System.IO.Path]::GetExtension($ImagePath).ToLower() | |
| if ($ext -notin $validExtensions) { | |
| Write-ColorMessage "[ERROR] Unsupported image format '$ext'. Use: PNG, JPEG, BMP, GIF, TIFF" -Type Error | |
| exit 1 | |
| } | |
| Write-ColorMessage " [✓] Source image: $ImagePath" -Type Success | |
| # Step 2 (2/7): Check if Edge is running | |
| Write-ColorMessage "`n[2/7] Checking if Microsoft Edge is running..." -Type Info | |
| if (Test-EdgeRunning) { | |
| Write-ColorMessage "`n[ERROR] Microsoft Edge is currently running!" -Type Error | |
| Write-Host "`nPlease close all Edge windows and try again." -ForegroundColor Yellow | |
| Write-Host "To close Edge completely:" | |
| Write-Host " 1. Close all Edge windows" | |
| Write-Host " 2. Check system tray for Edge icon and quit it" | |
| Write-Host " 3. Or run: Stop-Process -Name msedge -Force" | |
| exit 1 | |
| } | |
| Write-ColorMessage " [✓] Edge is not running" -Type Success | |
| # Step 3 (3/7): Get and display profiles | |
| Write-ColorMessage "`n[3/7] Loading Edge profiles..." -Type Info | |
| $profiles = Get-EdgeProfiles | |
| if ($profiles.Count -eq 0) { | |
| Write-ColorMessage "[ERROR] No Edge profiles found!" -Type Error | |
| exit 1 | |
| } | |
| Write-ColorMessage " [✓] Found $($profiles.Count) profile(s)" -Type Success | |
| # Step 4 (4/7): Select profile | |
| Show-ProfileList -Profiles $profiles | |
| Write-Host "`nEnter the number of the profile to update (or 'q' to quit): " -NoNewline -ForegroundColor Yellow | |
| $selection = Read-Host | |
| if ($selection -eq 'q') { | |
| Write-ColorMessage "`nOperation cancelled by user." -Type Warning | |
| exit 0 | |
| } | |
| $index = [int]$selection - 1 | |
| if ($index -lt 0 -or $index -ge $profiles.Count) { | |
| Write-ColorMessage "`n[ERROR] Invalid selection!" -Type Error | |
| exit 1 | |
| } | |
| $selectedProfile = $profiles[$index] | |
| Write-Host "`n" | |
| Write-ColorMessage "[5/7] Selected Profile:" -Type Info | |
| Write-Host " Name: $($selectedProfile.Name)" -ForegroundColor White | |
| Write-Host " Key: $($selectedProfile.Key)" -ForegroundColor Gray | |
| Write-Host " Has Picture: $($selectedProfile.HasPicture)" -ForegroundColor $(if ($selectedProfile.HasPicture) { 'Green' } else { 'Gray' }) | |
| # Confirm | |
| Write-Host "`nThis will replace the profile picture for '$($selectedProfile.Name)'." | |
| Write-Host "Do you want to continue? (y/N): " -NoNewline -ForegroundColor Yellow | |
| $confirm = Read-Host | |
| if ($confirm -ne 'y') { | |
| Write-ColorMessage "`nOperation cancelled by user." -Type Warning | |
| exit 0 | |
| } | |
| # Step 5 (6/7): Create backups | |
| Write-ColorMessage "`n[6/7] Creating backups..." -Type Info | |
| $backupPath = New-BackupDirectory | |
| Write-ColorMessage " Backup location: $backupPath" -Type Info | |
| Backup-ProfileFiles -ProfileKey $selectedProfile.Key -BackupPath $backupPath | |
| # Step 6 (7/7): Apply image changes | |
| Write-ColorMessage "`n[7/7] Applying image changes..." -Type Info | |
| $tempResized = Join-Path $env:TEMP "EdgeProfilePicture_resized_$(Get-Date -Format 'yyyyMMddHHmmss').png" | |
| try { | |
| Invoke-ImageResize -SourcePath $ImagePath -DestPath $tempResized | |
| Set-ProfilePicture -ProfileKey $selectedProfile.Key -ResizedImagePath $tempResized | |
| } finally { | |
| if (Test-Path $tempResized) { Remove-Item $tempResized -Force -ErrorAction SilentlyContinue } | |
| } | |
| # Verification | |
| Write-ColorMessage "`nVerifying changes..." -Type Info | |
| $userDataPath = Get-EdgeUserDataPath | |
| $utf8 = [System.Text.UTF8Encoding]::new($false) | |
| $localState = [System.IO.File]::ReadAllText((Join-Path $userDataPath 'Local State'), $utf8) | ConvertFrom-Json | |
| $entry = $localState.profile.info_cache.($selectedProfile.Key) | |
| if ($entry.use_gaia_picture -eq $true) { | |
| Write-ColorMessage " [✓] use_gaia_picture = true" -Type Success | |
| } else { | |
| Write-ColorMessage " [!] use_gaia_picture is not true" -Type Warning | |
| } | |
| $picturePath = Join-Path $userDataPath "$($selectedProfile.Key)\Edge Profile Picture.png" | |
| if (Test-Path $picturePath) { | |
| Write-ColorMessage " [✓] Edge Profile Picture.png exists in profile directory" -Type Success | |
| } else { | |
| Write-ColorMessage " [!] Edge Profile Picture.png not found in profile directory" -Type Warning | |
| } | |
| # Success summary | |
| Write-Host "`n" | |
| Write-ColorMessage "╔═══════════════════════════════════════════════════════════════╗" -Type Success | |
| Write-ColorMessage "║ SUCCESS! Profile image updated ║" -Type Success | |
| Write-ColorMessage "╚═══════════════════════════════════════════════════════════════╝" -Type Success | |
| Write-Host "`n" | |
| Write-ColorMessage "Next steps:" -Type Info | |
| Write-Host " 1. Open Microsoft Edge with the '$($selectedProfile.Name)' profile" | |
| Write-Host " 2. Check the profile icon (top-right) or edge://settings/profiles" | |
| Write-Host "`n" | |
| Write-ColorMessage "Backup location: $backupPath" -Type Info | |
| Show-RollbackInstructions -BackupPath $backupPath -ProfileKey $selectedProfile.Key | |
| } catch { | |
| Write-Host "`n" | |
| Write-ColorMessage "╔═══════════════════════════════════════════════════════════════╗" -Type Error | |
| Write-ColorMessage "║ ERROR OCCURRED ║" -Type Error | |
| Write-ColorMessage "╚═══════════════════════════════════════════════════════════════╝" -Type Error | |
| Write-Host "`n" | |
| Write-ColorMessage "Error: $($_.Exception.Message)" -Type Error | |
| Write-Host "`nStack Trace:" -ForegroundColor Gray | |
| Write-Host $_.ScriptStackTrace -ForegroundColor Gray | |
| if ($backupPath -and (Test-Path $backupPath)) { | |
| Write-Host "`n" | |
| Write-ColorMessage "Backups were created at: $backupPath" -Type Warning | |
| Write-ColorMessage "You can use these to restore if needed." -Type Warning | |
| } | |
| exit 1 | |
| } | |
| #endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment