Skip to content

Instantly share code, notes, and snippets.

@skarllot
Last active January 2, 2026 11:27
Show Gist options
  • Select an option

  • Save skarllot/1dfeab6c180cf85dd9250c308712f3c7 to your computer and use it in GitHub Desktop.

Select an option

Save skarllot/1dfeab6c180cf85dd9250c308712f3c7 to your computer and use it in GitHub Desktop.
Convert Microsoft Edge Work/School Profile to Personal Profile - Allows signing in with personal Microsoft accounts (MSA) instead of requiring corporate Azure AD accounts
<#
.SYNOPSIS
Converts a Microsoft Edge Work/School profile to a Personal profile.
.DESCRIPTION
This script converts an Edge profile that was created as a Work/School profile
(requiring Azure AD/Entra ID corporate accounts) to a Personal profile that
accepts personal Microsoft accounts (MSA).
The script:
- Checks if Edge is running (exits if it is)
- Lists all Edge profiles and their types
- Creates automatic backups in your home directory
- Removes the work profile marker (kodiak.work.profile)
- Changes the profile type from Work/School to Personal
- Provides rollback instructions if needed
.PARAMETER ProfileName
Optional. The name of the profile to convert (e.g., "Profile 1", "Default").
If not specified, the script will display a list of profiles to choose from.
.EXAMPLE
.\Convert-EdgeWorkProfileToPersonal.ps1
Runs the script interactively, prompting you to select a profile.
.EXAMPLE
.\Convert-EdgeWorkProfileToPersonal.ps1 -ProfileName "Profile 1"
Converts the specified profile directly.
.NOTES
Version: 1.0
IMPORTANT: Close Microsoft Edge completely before running this script.
Backups are created automatically in: $env:USERPROFILE\EdgeProfileBackup_[timestamp]\
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$false)]
[string]$ProfileName
)
$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"
}
$localState = Get-Content $localStatePath -Raw | ConvertFrom-Json
$profiles = @()
foreach ($profileKey in $localState.profile.info_cache.PSObject.Properties.Name) {
$profileData = $localState.profile.info_cache.$profileKey
$profileType = switch ($profileData.edge_non_signin_profile_type) {
1 { 'Personal' }
2 { 'Work/School' }
default { 'Unknown' }
}
$profiles += [PSCustomObject]@{
Key = $profileKey
Name = $profileData.name
Type = $profileType
TypeValue = $profileData.edge_non_signin_profile_type
AccountEmail = $profileData.user_name
}
}
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]
$typeColor = if ($profile.Type -eq 'Work/School') { 'Yellow' } else { 'Green' }
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 "[$($profile.Type)]") -ForegroundColor $typeColor
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 "EdgeProfileBackup_$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 Profile Preferences
$preferencesPath = Join-Path $userDataPath "$ProfileKey\Preferences"
if (Test-Path $preferencesPath) {
$profileBackupDir = Join-Path $BackupPath $ProfileKey
New-Item -ItemType Directory -Path $profileBackupDir -Force | Out-Null
$preferencesBackup = Join-Path $profileBackupDir 'Preferences'
Copy-Item $preferencesPath $preferencesBackup -Force
Write-ColorMessage " [✓] Backed up: $ProfileKey\Preferences" -Type Success
}
return $true
}
function Convert-ProfileToPersonal {
param(
[string]$ProfileKey
)
$userDataPath = Get-EdgeUserDataPath
$changes = @()
# Change 1: Remove kodiak work profile marker from Preferences
Write-ColorMessage "`nApplying changes..." -Type Info
$preferencesPath = Join-Path $userDataPath "$ProfileKey\Preferences"
if (Test-Path $preferencesPath) {
$preferences = Get-Content $preferencesPath -Raw | ConvertFrom-Json
if ($preferences.PSObject.Properties.Name -contains 'kodiak') {
$preferences.PSObject.Properties.Remove('kodiak')
$preferences | ConvertTo-Json -Depth 100 -Compress | Set-Content $preferencesPath -Encoding UTF8
$changes += " [✓] Removed work profile marker (kodiak) from Preferences"
Write-ColorMessage $changes[-1] -Type Success
} else {
Write-ColorMessage " [→] No kodiak marker found in Preferences (already personal?)" -Type Warning
}
}
# Change 2: Update profile type in Local State
$localStatePath = Join-Path $userDataPath 'Local State'
$localState = Get-Content $localStatePath -Raw | ConvertFrom-Json
$currentType = $localState.profile.info_cache.$ProfileKey.edge_non_signin_profile_type
if ($currentType -eq 2) {
$localState.profile.info_cache.$ProfileKey.edge_non_signin_profile_type = 1
$localState | ConvertTo-Json -Depth 100 -Compress | Set-Content $localStatePath -Encoding UTF8
$changes += " [✓] Changed profile type from Work/School (2) to Personal (1)"
Write-ColorMessage $changes[-1] -Type Success
} elseif ($currentType -eq 1) {
Write-ColorMessage " [→] Profile type already set to Personal (1)" -Type Warning
} else {
Write-ColorMessage " [!] Unknown profile type: $currentType" -Type Warning
}
return $changes
}
function Show-RollbackInstructions {
param([string]$BackupPath)
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 " Copy-Item (Join-Path `$backupPath 'Profile X\Preferences') `$userDataPath -Recurse -Force" -ForegroundColor Cyan
Write-Host ""
}
#endregion
#region Main Script
try {
Write-Host "`n"
Write-ColorMessage "╔═══════════════════════════════════════════════════════════════╗" -Type Info
Write-ColorMessage "║ Edge Work Profile to Personal Profile Converter ║" -Type Info
Write-ColorMessage "╚═══════════════════════════════════════════════════════════════╝" -Type Info
Write-Host "`n"
# Step 1: Check if Edge is running
Write-ColorMessage "[1/6] 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 2: Get and display profiles
Write-ColorMessage "`n[2/6] 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 3: Select profile
if (-not $ProfileName) {
Show-ProfileList -Profiles $profiles
Write-Host "`nEnter the number of the profile to convert (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]
} else {
$selectedProfile = $profiles | Where-Object { $_.Key -eq $ProfileName -or $_.Name -eq $ProfileName } | Select-Object -First 1
if (-not $selectedProfile) {
Write-ColorMessage "[ERROR] Profile '$ProfileName' not found!" -Type Error
exit 1
}
}
Write-Host "`n"
Write-ColorMessage "[3/6] Selected Profile:" -Type Info
Write-Host " Name: $($selectedProfile.Name)" -ForegroundColor White
Write-Host " Key: $($selectedProfile.Key)" -ForegroundColor Gray
Write-Host " Current Type: $($selectedProfile.Type)" -ForegroundColor $(if ($selectedProfile.Type -eq 'Work/School') { 'Yellow' } else { 'Green' })
if ($selectedProfile.Type -ne 'Work/School') {
Write-ColorMessage "`n[!] This profile is not a Work/School profile." -Type Warning
Write-Host "It may already be configured as Personal. Continue anyway? (y/N): " -NoNewline
$confirm = Read-Host
if ($confirm -ne 'y') {
Write-ColorMessage "`nOperation cancelled." -Type Warning
exit 0
}
}
# Step 4: Confirm
Write-Host "`nThis will convert the profile to allow personal Microsoft account sign-in."
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: Create backups
Write-ColorMessage "`n[4/6] Creating backups..." -Type Info
$backupPath = New-BackupDirectory
Write-ColorMessage " Backup location: $backupPath" -Type Info
Backup-ProfileFiles -ProfileKey $selectedProfile.Key -BackupPath $backupPath
# Step 6: Convert profile
Write-ColorMessage "`n[5/6] Converting profile..." -Type Info
$changes = Convert-ProfileToPersonal -ProfileKey $selectedProfile.Key
# Step 7: Verification
Write-ColorMessage "`n[6/6] Verifying changes..." -Type Info
$updatedProfiles = Get-EdgeProfiles
$updatedProfile = $updatedProfiles | Where-Object { $_.Key -eq $selectedProfile.Key }
if ($updatedProfile.Type -eq 'Personal') {
Write-ColorMessage " [✓] Profile type successfully changed to Personal" -Type Success
} else {
Write-ColorMessage " [!] Profile type is: $($updatedProfile.Type)" -Type Warning
}
# Success summary
Write-Host "`n"
Write-ColorMessage "╔═══════════════════════════════════════════════════════════════╗" -Type Success
Write-ColorMessage "║ SUCCESS! Profile conversion completed ║" -Type Success
Write-ColorMessage "╚═══════════════════════════════════════════════════════════════╝" -Type Success
Write-Host "`n"
Write-ColorMessage "Changes applied:" -Type Info
foreach ($change in $changes) {
Write-Host $change
}
Write-Host "`n"
Write-ColorMessage "Next steps:" -Type Info
Write-Host " 1. Open Microsoft Edge with the '$($selectedProfile.Name)' profile"
Write-Host " 2. Try signing in with your personal Microsoft account"
Write-Host " 3. Enable sync if desired"
Write-Host "`n"
Write-ColorMessage "Backup location: $backupPath" -Type Info
Show-RollbackInstructions -BackupPath $backupPath
} 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