Create and configure your Edge profiles with PowerShell

Create and configure your Edge profiles with PowerShell header image

Are you looking for an efficient way to create and configure your Microsoft Edge profile? You might have seen my previous blog on to create a new profile for Edge with PowerShell. PowerShell makes it easy to save time and effort when creating your Edge profiles, something I do quite often as a consultant. It did however bother me for years that I had to manually configure the name of the profile and the settings I wanted to use. I wanted to automate this as well, and after some complaining on Twitter I got some great feedback on how to achieve this! Andi Krüger and Leon Zandman pointed me to Procmon. So that got me hyped again 🔥.

How to create a Microsoft Edge profile with PowerShell?

In my the first version of the blog the provisioning of a profile is done by calling the msedge.exe process with some parameters. While this does create a new profile those profiles always are called something like Profile 1 while the folder that gets created does contain the customer name that is passed to the initial script.

Using Procmon I was able to find out what files and registry settings are being used and need to be updated as part of a rename. Turns out that a file called Local State contains all the values and the Registry contains the Profile name as well. THe biggest challenge is that the Local State file only gets updated after you close the browser. So we need to close the browser after we have started it using PowerShell.

$proc = Start-Process -FilePath "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" -ArgumentList "--profile-directory=$profilePath --no-first-run --no-default-browser-check" --passThru

$proc | Wait-Process -Timeout 6 -ErrorAction SilentlyContinue -ErrorVariable timeouted

However I had some minor issues when I had multiple Edge windows open. For some reason it would overwrite my changed names so it might keep something in the cache somewhere and reuse that to overwrite your changes. To prevent that I just close all Edge windows using a slightly more drastic approach

Stop-Process -Name "msedge"

Next up is editing the Local State file. This file is a JSON file so we can use the ConvertFrom-Json and ConvertTo-Json cmdlets to read and write the file. The file contains a lot of settings, and feel free to go through them yourself. FOr our use case the actual name we need the profile.info_cache value, as that contains a name value as part of the profile we just created. We can do this by using the Select-Object or thread it like an object.

$localStateFile = "$Env:LOCALAPPDATA\Microsoft\Edge\User Data\Local State"
$state = Get-Content -Raw $localStateFile
$json = $state | ConvertFrom-Json
$edgeProfile = $json.profile.info_cache.$profilePath
Write-Output "Old profile name: $($edgeProfile.name)"
$edgeProfile.name = "New Name"
# Only execute when you know what you are doing
$json | ConvertTo-Json -Compress -Depth 100 | Out-File $localStateFile

Saving the Local State file without knowing what you are doing is a bit risky; as with a corrupted version you loose all your settings and profiles. So I would recommend to test it by creating a backup first, just a copy of the local state file before editing would suffice.

Editing the registry works almost the same way; each profile has a ShortcutName value that contains the name of the profile. We can use the Set-ItemProperty cmdlet to update the value since we know the location of the profile.

Write-Output "Write profile name to registry: $($edgeProfile.name)"
Push-Location
Set-Location HKCU:\Software\Microsoft\Edge\Profiles\$profilePath
Set-ItemProperty . ShortcutName "$customerName"
Pop-Location

How to configure the name of the profile and your desired settings?

Editing settings turned to be a bit more time consuming. I figured out that the Local State file contains a lot of settings, but not the settings for the profile it self. These type of settings are stored in the Preferences file that is created in the profile folder. This file is a JSON file as well, so we can use the same approach as we did for the Local State file. The only weird things is that the Preference file is created with a bit of a delay. So if we use the Stop-Process to soon after creating a new profile it might not be there yet. On my machine the sweet spot was somewhere between ~10 seconds waiting so in the script I opted for waiting 15 seconds to make sure everything was there. Then finally you can load the preferences file, work with it and save it again.

It takes a bit of fiddling to figure out what setting you are looking for, for instance the right sidebar you get with a new profile, and that in the menu is called sidebar, all of a sudden is called show_hub_apps_tower in the Preferences file. So you need to do some digging to figure out what setting you are looking for.

$preferenceSettings = "$Env:LOCALAPPDATA\Microsoft\Edge\User Data\$profilePath\Preferences"

$preferences = Get-Content -Raw $preferenceSettings
$preferenceJson = $preferences | ConvertFrom-Json

if ($null -eq $preferenceJson.browser.show_hub_apps_tower) {
    Write-Output "Sidebar is not set and turned on by default, lets disable it"

    $preferenceJson.browser | add-member -Name "show_hub_apps_tower" -value $false -MemberType NoteProperty
}
else {
    $sideBarToggle = $preferenceJson.browser.show_hub_apps_tower
    Write-Output "Sidebar is set to: $sideBarToggle lets make it false"
    $preferenceJson.browser.show_hub_apps_tower = $false #disable side bar
}

Additionally we want to the sharing of data with other Windows features to be disabled; this ensures that we run in a more isolated environment. We can enable this with the following code:

if ($null -eq $preferenceJson.local_browser_data_share.enabled) {
    Write-Output "Disable data share between profiles"
    $blockvalue =@"
    {
        "enabled": false,
        "index_last_cleaned_time": "0"
    }
"@

    $preferenceJson | add-member -Name "local_browser_data_share" -value (Convertfrom-Json $blockvalue) -MemberType NoteProperty
}
else {
    Write-Output "Disable data share between profiles"

    $preferenceJson.local_browser_data_share.enabled = $false; #disable sharing data between profiles
}

Additionally we want to disable the default copy paste experience for the ‘old school’ copy paste. I just want the URL by default, not the ‘rich’ experience that is turned on by default:

if ($null -eq $preferenceJson.edge_share) {
    Write-Output "Disable enhanced copy paste"
    $blockvalue =@"
    {
        "enhanced_copy_paste": {
            "default_url_format": 1,
            "enable_secondary_ecp": true
        }
    }
"@

    $preferenceJson | add-member -Name "edge_share" -value (Convertfrom-Json $blockvalue) -MemberType NoteProperty
}
else {
    Write-Output "Disable enhanced copy paste"

    $preferenceJson.edge_share.enhanced_copy_paste.default_url_format = 1; #disable enhanced copy paste
}

The result

The final result of the whole script is tweaked slightly; it takes into account creating a backup file to make sure we can go back in time to the previous state. My preferences where to disable the right side bar and turn on vertical tabs. But you can tweak other settings as well!


Param(
    [Parameter(Mandatory = $true)]
    [string]
    $customerName,
    [Parameter(Mandatory = $false)]
    [bool]
    $createBackup = $true
)

Write-Output "Creating Edge profile for $customerName"

$profilePath = "profile-" + $customerName.replace(' ', '-')
$proc = Start-Process -FilePath "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" -ArgumentList "--profile-directory=$profilePath --no-first-run --no-default-browser-check --flag-switches-begin --flag-switches-end --site-per-process" -PassThru

Write-Output "Profile $customerName created, wait 15 seconds before closing Edge"

Start-Sleep -Seconds 15 #it takes roughly 15 seconds to prepare the profile and write all files to disk.
Stop-Process -Name "msedge"

# Edit profile name
$localStateFile = "$Env:LOCALAPPDATA\Microsoft\Edge\User Data\Local State"

if ($createBackup) {
    $localStateBackUp = "$Env:LOCALAPPDATA\Microsoft\Edge\User Data\Local State Backup"
    Copy-Item $localStateFile -Destination $localStateBackUp
}

$state = Get-Content -Raw $localStateFile
$json = $state | ConvertFrom-Json

$edgeProfile = $json.profile.info_cache.$profilePath

Write-Output "Found profile $profilePath"
Write-Output "Old profile name: $($edgeProfile.name)"

$edgeProfile.name = $customerName

Write-Output "Write profile name to local state: $($edgeProfile.name)"

# Only uncomment the next line if you know what you're doing!!
$json | ConvertTo-Json -Compress -Depth 100 | Out-File $localStateFile

Write-Output "Write profile name to registry: $($edgeProfile.name)"
Push-Location
Set-Location HKCU:\Software\Microsoft\Edge\Profiles\$profilePath
Set-ItemProperty . ShortcutName "$customerName"
Pop-Location

$preferenceSettings = "$Env:LOCALAPPDATA\Microsoft\Edge\User Data\$profilePath\Preferences"

if ($createBackup) {
    $preferenceSettingsBackup = "$Env:LOCALAPPDATA\Microsoft\Edge\User Data\$profilePath\Preferences Backup"
    Copy-Item $preferenceSettings -Destination $preferenceSettingsBackup
}

$preferences = Get-Content -Raw $preferenceSettings
$preferenceJson = $preferences | ConvertFrom-Json

if ($null -eq $preferenceJson.browser.show_hub_apps_tower) {
    Write-Output "Sidebar is not set and turned on by default, lets disable it"

    $preferenceJson.browser | add-member -Name "show_hub_apps_tower" -value $false -MemberType NoteProperty
}
else {
    $sideBarToggle = $preferenceJson.browser.show_hub_apps_tower
    Write-Output "Sidebar is set to: $sideBarToggle lets make it false"
    $preferenceJson.browser.show_hub_apps_tower = $false #disable side bar
}

if ($null -eq $preferenceJson.edge.vertical_tabs.collapsed) {
    Write-Output "Vertical tabs are turned off by default, lets enable it"

    $preferenceJson.edge.vertical_tabs | add-member -Name "collapsed" -value $true -MemberType NoteProperty
    $preferenceJson.edge.vertical_tabs | add-member -Name "first_opened2" -value $true -MemberType NoteProperty
    $preferenceJson.edge.vertical_tabs | add-member -Name "opened" -value $true -MemberType NoteProperty
}
else {
    $verticalTabs = $preferenceJson.edge.vertical_tabs.collapsed
    Write-Output "Vertical Tabs are set to: $verticalTabs, lets enable it"
    $preferenceJson.edge.vertical_tabs.collapsed = $true #enable vertical tabs
    $preferenceJson.edge.vertical_tabs.first_opened2 = $true #enable vertical tabs
    $preferenceJson.edge.vertical_tabs.opened = $true #enable vertical tabs
}

if ($null -eq $preferenceJson.local_browser_data_share.enabled) {
    Write-Output "Disable data share between profiles"
    $blockvalue =@"
    {
        "enabled": false,
        "index_last_cleaned_time": "0"
    }
"@

    $preferenceJson | add-member -Name "local_browser_data_share" -value (Convertfrom-Json $blockvalue) -MemberType NoteProperty
}
else {
    Write-Output "Disable data share between profiles"

    $preferenceJson.local_browser_data_share.enabled = $false; #disable sharing data between profiles
}

if ($null -eq $preferenceJson.edge_share) {
    Write-Output "Disable enhanced copy paste"
    $blockvalue =@"
    {
        "enhanced_copy_paste": {
            "default_url_format": 1,
            "enable_secondary_ecp": true
        }
    }
"@

    $preferenceJson | add-member -Name "edge_share" -value (Convertfrom-Json $blockvalue) -MemberType NoteProperty
}
else {
    Write-Output "Disable enhanced copy paste"

    $preferenceJson.edge_share.enhanced_copy_paste.default_url_format = 1; #disable enhanced copy paste
}

Write-Output "Write new settings to $($profilePath)"

# Only uncomment the next line if you know what you're doing!!
$preferenceJson | ConvertTo-Json -Compress -Depth 100 | Out-File $preferenceSettings

Write-Output "Done, you can start browsing with your new profile"

Calling the script is straight forward and you are presented with basic output:

Calling the script in Windows Terminal

It takes about 15 seconds for the script to run and create your profile. If you feel adventurous you can tweak those 15 seconds a bit more and perhaps shave it back to 10’ish. I had mixed results though so if you want to play it save keep it like it is 😉.

Calling the script in WIndows Terminal

A final remark is that this is all undocumented so the json schema might change with future releases. I usually try to update scripts when the break and I need them, but you might find other behavior as Edge gets update quite frequently. I hope this helps you to get started with Edge and PowerShell and let me know if you have any questions or remarks! For me when migrating computers and having to recreate 10+ profiles this is a huge time saver!

Update

For an updated and improved version of the PowerShell script for creating and configuring Microsoft Edge profiles, check out the latest blog post at Create and configure your Edge profiles with PowerShell. Discover how to streamline the process and unlock advanced customization options for the sidebar, start page, and more!

Loading comments…