Skip to main content
added 150 characters in body
Source Link
mklement0
  • 2.1k
  • 1
  • 18
  • 23
  • Aldis's helpful answer points to a third-party utility that, SetDefaultBrowser.exe, which works robustly, because it doesn't rely on GUI scripting, i.e. on simulating user input programmatically, which is invariably brittle (doesn't always work) and cannot be used from environments that run without a Windows desktop.

  • The other answers here are GUI-scripting solutions - and most no longer work in recent version of Windows 10 and on Windows 11.

  • Aldis's helpful answer points to a third-party utility that works robustly, because it doesn't rely on GUI scripting, i.e. on simulating user input programmatically, which is invariably brittle (doesn't always work) and cannot be used from environments that run without a Windows desktop.

  • The other answers here are GUI-scripting solutions - and most no longer work in recent version of Windows 10 and on Windows 11.

  • Aldis's helpful answer points to a third-party utility, SetDefaultBrowser.exe, which works robustly, because it doesn't rely on GUI scripting, i.e. on simulating user input programmatically, which is invariably brittle (doesn't always work) and cannot be used from environments that run without a Windows desktop.

  • The other answers here are GUI-scripting solutions - and most no longer work in recent version of Windows 10 and on Windows 11.

added 71 characters in body
Source Link
mklement0
  • 2.1k
  • 1
  • 18
  • 23
  • Aldis's helpful answer points to a third-party utility that works robustly, because it doesn't rely on GUI scripting, i.e. on simulating user input programmatically, which is invariably brittleinvariably brittle (doesn't always work) and cannot be used from environments that run without a Windows desktop.

  • The other answers here are GUI-scripting solutions - and most no longer work in recent version of Windows 10 and on Windows 11.

function Set-DefaultBrowser {
  <#
.SYNOPSIS
  Sets the default web browser for the current user (Windows only).

.DESCRIPTION
  Specify the display name of the target browser, 
  as shown in the Default Apps page of the Settings app.

  Examples: 'Brave', 'Google Chrome', 'Microsoft Edge'

  IMPORTANT: 
    * Uses GUI SCRIPTING, which implies:
      * This script can only run in sessions with a visible desktop.
      * As all GUI scripting, it is *brittle*.
    * If the Windwos Settings app is currently open, it will
      be forcefully closed first.
  
.PARAMETER BrowserDisplayName
  Specify the display name of the target browser, 
  as shown in the Default Apps page of the Settings app.
  (Start-Process ms-settings:defaultapps)

  If you use a substring, be sure that it matches the 
  desired application (as the first match).

  Also be sure that the name matches an actual installed
  *browser* application.

.PARAMETER KeepSettingsOpen
  Keeps the Settings app open after having made the change.
  By default, it is closed automatically.

.PARAMETER OpenSampleUrl
  Opens URL https://example.org in the default browser after
  having made the change, for visual verification that the change
  took effect.

.EXAMPLE
  Set-DefaultBrowser Brave
  Makes Brave the default browser for the current user.

.EXAMPLE
  Set-DefaultBrowser 'Google Chrome' -KeepSettingsOpen
  Makes Chrome the default browser for the current user 
  and leaves the Settings app open after doing so.

.EXAMPLE
  Set-DefaultBrowser 'Microsoft Edge' -OpenSampleUrl
  Makes Edge the default browser for the current user 
  and opens a sample URL afterwards for visual verification
  that the change took effect.
#>

  [CmdletBinding(PositionalBinding = $false)]
  param(
    [Parameter(Mandatory, Position = 0)]
    [string] $BrowserDisplayName,
    [switch] $KeepSettingsOpen,
    [switch] $OpenSampleUrl
  )

  if ($env:OS -ne 'Windows_NT') { throw 'This script runs on Windows only.' }

  # If the Settings app is currently open, it could be in a state that interferes
  # with the GUI scripting below.
  # Therefore, we kill any existing instance.
  Stop-Process -ErrorAction Ignore -Name SystemSettings
  # If you'd rather not kill an existing instance, use the following:
  #   if (Get-Process -ErrorAction Ignore SystemSettings) { throw "The Settings application is currently open. Close it before running this script." }

  # Launch the Default Apps page of the Settings app.
  Start-Process ms-settings:defaultapps

  # Wait for the Settings page to open and be ready for user input.
  # You may have to tweak this.
  # !! Curiously, the SystemSettings process *initially, briefly* has a non-zero
  # !! .MainWindowHandle property, which becomes zero once the window actually shows.
  # !! We take this transition to imply that the windows is ready for user input.
  $ps = Get-Process -ErrorAction Stop SystemSettings
  do {
    Start-Sleep -Milliseconds 100
    $ps.Refresh()
  } while ([int] $ps.MainWindowHandle)
  Start-Sleep -Milliseconds 200 # Sleep a little, to be safe.

  # Start sending keystrokes.
  $shell = New-Object -ComObject WScript.Shell 

  # Tab to the "Set defaults for applications" search field.
  # Sleep a little between the keystrokes, for more predictable results.
  foreach ($i in 1..4) { $shell.SendKeys('{TAB}'); Start-Sleep -Milliseconds 30 } 

  # Send the target browser's display name, which triggers a search.
  $shell.SendKeys($BrowserDisplayName)

  # Select the (first) search result to go to its details page.
  Start-Sleep -Milliseconds 100
  $shell.SendKeys('{TAB}  ')

  # Sleep a little so that the application-details page has a chance to open,
  # then click the 'Set Default` button.
  Start-Sleep -Milliseconds 500
  $shell.SendKeys(' ')

  # Close the window, unless requested not to.
  if (-not $KeepSettingsOpen) {
    $shell.SendKeys('%{F4}')
  }

  # Open a sample URL in the new default browser, if requested.
  if ($OpenSampleUrl) {
    Start-Process https://example.org
  }

}
  • Aldis's helpful answer points to a third-party utility that works robustly, because it doesn't rely on GUI scripting, i.e. on simulating user input programmatically, which is invariably brittle (doesn't always work) and cannot be used from environments that run without a Windows desktop.

  • The other answers here are GUI-scripting solutions - and most no longer work in recent version of Windows 10 and on Windows 11.

function Set-DefaultBrowser {
  <#
.SYNOPSIS
  Sets the default web browser for the current user (Windows only).

.DESCRIPTION
  Specify the display name of the target browser, 
  as shown in the Default Apps page of the Settings app.

  Examples: 'Brave', 'Google Chrome', 'Microsoft Edge'

  IMPORTANT: 
    * Uses GUI SCRIPTING, which implies:
      * This script can only run in sessions with a visible desktop.
      * As all GUI scripting, it is *brittle*.
    * If the Windwos Settings app is currently open, it will
      be forcefully closed first.
  
.PARAMETER BrowserDisplayName
  Specify the display name of the target browser, 
  as shown in the Default Apps page of the Settings app.
  (Start-Process ms-settings:defaultapps)

  If you use a substring, be sure that it matches the 
  desired application (as the first match).

  Also be sure that the name matches an actual installed
  *browser* application.

.PARAMETER KeepSettingsOpen
  Keeps the Settings app open after having made the change.
  By default, it is closed automatically.

.PARAMETER OpenSampleUrl
  Opens URL https://example.org in the default browser after
  having made the change, for visual verification that the change
  took effect.

.EXAMPLE
  Set-DefaultBrowser Brave
  Makes Brave the default browser for the current user.

.EXAMPLE
  Set-DefaultBrowser 'Google Chrome' -KeepSettingsOpen
  Makes Chrome the default browser for the current user 
  and leaves the Settings app open after doing so.

.EXAMPLE
  Set-DefaultBrowser 'Microsoft Edge' -OpenSampleUrl
  Makes Edge the default browser for the current user 
  and opens a sample URL afterwards for visual verification
  that the change took effect.
#>

  [CmdletBinding(PositionalBinding = $false)]
  param(
    [Parameter(Mandatory, Position = 0)]
    [string] $BrowserDisplayName,
    [switch] $KeepSettingsOpen,
    [switch] $OpenSampleUrl
  )

  if ($env:OS -ne 'Windows_NT') { throw 'This script runs on Windows only.' }

  # If the Settings app is currently open, it could be in a state that interferes
  # with the GUI scripting below.
  # Therefore, we kill any existing instance.
  Stop-Process -ErrorAction Ignore -Name SystemSettings
  # If you'd rather not kill an existing instance, use the following:
  #   if (Get-Process -ErrorAction Ignore SystemSettings) { throw "The Settings application is currently open. Close it before running this script." }

  # Launch the Default Apps page of the Settings app.
  Start-Process ms-settings:defaultapps

  # Wait for the Settings page to open and be ready for user input.
  # You may have to tweak this.
  # !! Curiously, the SystemSettings process *initially, briefly* has a non-zero
  # !! .MainWindowHandle property, which becomes zero once the window actually shows.
  # !! We take this transition to imply that the windows is ready for user input.
  $ps = Get-Process -ErrorAction Stop SystemSettings
  do {
    Start-Sleep -Milliseconds 100
    $ps.Refresh()
  } while ([int] $ps.MainWindowHandle)
  Start-Sleep -Milliseconds 200 # Sleep a little, to be safe.

  # Start sending keystrokes.
  $shell = New-Object -ComObject WScript.Shell
  # Tab to the "Set defaults for applications" search field.
  # Sleep a little between the keystrokes, for more predictable results.
  foreach ($i in 1..4) { $shell.SendKeys('{TAB}'); Start-Sleep -Milliseconds 30 }

  $shell.SendKeys($BrowserDisplayName)

  # Select the (first) search result to go to its details page.
  Start-Sleep -Milliseconds 100
  $shell.SendKeys('{TAB}  ')

  # Sleep a little so that the application-details page has a chance to open,
  # then click the 'Set Default` button.
  Start-Sleep -Milliseconds 500
  $shell.SendKeys(' ')

  # Close the window, unless requested not to.
  if (-not $KeepSettingsOpen) {
    $shell.SendKeys('%{F4}')
  }

  # Open a sample URL in the new default browser, if requested.
  if ($OpenSampleUrl) {
    Start-Process https://example.org
  }

}
  • Aldis's helpful answer points to a third-party utility that works robustly, because it doesn't rely on GUI scripting, i.e. on simulating user input programmatically, which is invariably brittle (doesn't always work) and cannot be used from environments that run without a Windows desktop.

  • The other answers here are GUI-scripting solutions - and most no longer work in recent version of Windows 10 and on Windows 11.

function Set-DefaultBrowser {
  <#
.SYNOPSIS
  Sets the default web browser for the current user (Windows only).

.DESCRIPTION
  Specify the display name of the target browser, 
  as shown in the Default Apps page of the Settings app.

  Examples: 'Brave', 'Google Chrome', 'Microsoft Edge'

  IMPORTANT: 
    * Uses GUI SCRIPTING, which implies:
      * This script can only run in sessions with a visible desktop.
      * As all GUI scripting, it is *brittle*.
    * If the Windwos Settings app is currently open, it will
      be forcefully closed first.
  
.PARAMETER BrowserDisplayName
  Specify the display name of the target browser, 
  as shown in the Default Apps page of the Settings app.
  (Start-Process ms-settings:defaultapps)

  If you use a substring, be sure that it matches the 
  desired application (as the first match).

  Also be sure that the name matches an actual installed
  *browser* application.

.PARAMETER KeepSettingsOpen
  Keeps the Settings app open after having made the change.
  By default, it is closed automatically.

.PARAMETER OpenSampleUrl
  Opens URL https://example.org in the default browser after
  having made the change, for visual verification that the change
  took effect.

.EXAMPLE
  Set-DefaultBrowser Brave
  Makes Brave the default browser for the current user.

.EXAMPLE
  Set-DefaultBrowser 'Google Chrome' -KeepSettingsOpen
  Makes Chrome the default browser for the current user 
  and leaves the Settings app open after doing so.

.EXAMPLE
  Set-DefaultBrowser 'Microsoft Edge' -OpenSampleUrl
  Makes Edge the default browser for the current user 
  and opens a sample URL afterwards for visual verification
  that the change took effect.
#>

  [CmdletBinding(PositionalBinding = $false)]
  param(
    [Parameter(Mandatory, Position = 0)]
    [string] $BrowserDisplayName,
    [switch] $KeepSettingsOpen,
    [switch] $OpenSampleUrl
  )

  if ($env:OS -ne 'Windows_NT') { throw 'This script runs on Windows only.' }

  # If the Settings app is currently open, it could be in a state that interferes
  # with the GUI scripting below.
  # Therefore, we kill any existing instance.
  Stop-Process -ErrorAction Ignore -Name SystemSettings
  # If you'd rather not kill an existing instance, use the following:
  #   if (Get-Process -ErrorAction Ignore SystemSettings) { throw "The Settings application is currently open. Close it before running this script." }

  # Launch the Default Apps page of the Settings app.
  Start-Process ms-settings:defaultapps

  # Wait for the Settings page to open and be ready for user input.
  # You may have to tweak this.
  # !! Curiously, the SystemSettings process *initially, briefly* has a non-zero
  # !! .MainWindowHandle property, which becomes zero once the window actually shows.
  # !! We take this transition to imply that the windows is ready for user input.
  $ps = Get-Process -ErrorAction Stop SystemSettings
  do {
    Start-Sleep -Milliseconds 100
    $ps.Refresh()
  } while ([int] $ps.MainWindowHandle)
  Start-Sleep -Milliseconds 200 # Sleep a little, to be safe.

  # Start sending keystrokes.
  $shell = New-Object -ComObject WScript.Shell 

  # Tab to the "Set defaults for applications" search field.
  # Sleep a little between the keystrokes, for more predictable results.
  foreach ($i in 1..4) { $shell.SendKeys('{TAB}'); Start-Sleep -Milliseconds 30 } 

  # Send the target browser's display name, which triggers a search.
  $shell.SendKeys($BrowserDisplayName)

  # Select the (first) search result to go to its details page.
  Start-Sleep -Milliseconds 100
  $shell.SendKeys('{TAB} ')

  # Sleep a little so that the application-details page has a chance to open,
  # then click the 'Set Default` button.
  Start-Sleep -Milliseconds 500
  $shell.SendKeys(' ')

  # Close the window, unless requested not to.
  if (-not $KeepSettingsOpen) {
    $shell.SendKeys('%{F4}')
  }

  # Open a sample URL in the new default browser, if requested.
  if ($OpenSampleUrl) {
    Start-Process https://example.org
  }

}
Source Link
mklement0
  • 2.1k
  • 1
  • 18
  • 23

Let me attempt a summary as of Windows 11:

  • Aldis's helpful answer points to a third-party utility that works robustly, because it doesn't rely on GUI scripting, i.e. on simulating user input programmatically, which is invariably brittle (doesn't always work) and cannot be used from environments that run without a Windows desktop.

  • The other answers here are GUI-scripting solutions - and most no longer work in recent version of Windows 10 and on Windows 11.

The only reason to use GUI scripting is if downloading said third-party utility (whose license is very permissive) is not an option.

Here's a PowerShell-based GUI-scripting solution that works in Windows 11 and presumably in Windows 10 too, but note:

  • As with any GUI scripting solution:

    • Fundamentally, it only works when run in an environment with a Windows desktop (i.e., it won't work when run via PowerShell remoting or from a scheduled task that runs whether or not a user is logged on, for instance).

    • It may stop working over time, as the targeted GUI may change.

  • If the Windows Settings app happens to be open when the function starts, it is forcefully terminated, so as to prevent the state of an existing window from interfering with the GUI scripting.

  • You can paste the Set-DefaultBrowser function below into your $PROFILE file if you want it to be available in future PowerShell sessions.

Assuming that the function Set-DefaultBrowser is already defined in your session (see below - just copying and pasting with Ctrl+V in an interactive PowerShell session should work), you can use it as follows::

Set-DefaultBrowser 'Google Chrome'
  • Use the target browser's display name as shown in the Default Apps page of the Settings App, which you can open with Start-Process ms-settings:defaultapps.

    • Other common display names are 'Brave' and 'Microsoft Edge'.
  • You'll see simulated user activity for ca. 3 seconds during which no user action should be taken.

    • If you want to visually verify that the change was effective, add the -OpenSampleUrl switch; separately, if you want to inspect the state of the Settings app after the GUI-scripting attempt, use switch -KeepSettingsOpen.

Set-DefaultBrowser source code:

  • Once defined, run Set-DefaultBrowser -? for concise help, and help Set-DefaultBrowser for detailed help.
function Set-DefaultBrowser {
  <#
.SYNOPSIS
  Sets the default web browser for the current user (Windows only).

.DESCRIPTION
  Specify the display name of the target browser, 
  as shown in the Default Apps page of the Settings app.

  Examples: 'Brave', 'Google Chrome', 'Microsoft Edge'

  IMPORTANT: 
    * Uses GUI SCRIPTING, which implies:
      * This script can only run in sessions with a visible desktop.
      * As all GUI scripting, it is *brittle*.
    * If the Windwos Settings app is currently open, it will
      be forcefully closed first.
  
.PARAMETER BrowserDisplayName
  Specify the display name of the target browser, 
  as shown in the Default Apps page of the Settings app.
  (Start-Process ms-settings:defaultapps)

  If you use a substring, be sure that it matches the 
  desired application (as the first match).

  Also be sure that the name matches an actual installed
  *browser* application.

.PARAMETER KeepSettingsOpen
  Keeps the Settings app open after having made the change.
  By default, it is closed automatically.

.PARAMETER OpenSampleUrl
  Opens URL https://example.org in the default browser after
  having made the change, for visual verification that the change
  took effect.

.EXAMPLE
  Set-DefaultBrowser Brave
  Makes Brave the default browser for the current user.

.EXAMPLE
  Set-DefaultBrowser 'Google Chrome' -KeepSettingsOpen
  Makes Chrome the default browser for the current user 
  and leaves the Settings app open after doing so.

.EXAMPLE
  Set-DefaultBrowser 'Microsoft Edge' -OpenSampleUrl
  Makes Edge the default browser for the current user 
  and opens a sample URL afterwards for visual verification
  that the change took effect.
#>

  [CmdletBinding(PositionalBinding = $false)]
  param(
    [Parameter(Mandatory, Position = 0)]
    [string] $BrowserDisplayName,
    [switch] $KeepSettingsOpen,
    [switch] $OpenSampleUrl
  )

  if ($env:OS -ne 'Windows_NT') { throw 'This script runs on Windows only.' }

  # If the Settings app is currently open, it could be in a state that interferes
  # with the GUI scripting below.
  # Therefore, we kill any existing instance.
  Stop-Process -ErrorAction Ignore -Name SystemSettings
  # If you'd rather not kill an existing instance, use the following:
  #   if (Get-Process -ErrorAction Ignore SystemSettings) { throw "The Settings application is currently open. Close it before running this script." }

  # Launch the Default Apps page of the Settings app.
  Start-Process ms-settings:defaultapps

  # Wait for the Settings page to open and be ready for user input.
  # You may have to tweak this.
  # !! Curiously, the SystemSettings process *initially, briefly* has a non-zero
  # !! .MainWindowHandle property, which becomes zero once the window actually shows.
  # !! We take this transition to imply that the windows is ready for user input.
  $ps = Get-Process -ErrorAction Stop SystemSettings
  do {
    Start-Sleep -Milliseconds 100
    $ps.Refresh()
  } while ([int] $ps.MainWindowHandle)
  Start-Sleep -Milliseconds 200 # Sleep a little, to be safe.

  # Start sending keystrokes.
  $shell = New-Object -ComObject WScript.Shell
  # Tab to the "Set defaults for applications" search field.
  # Sleep a little between the keystrokes, for more predictable results.
  foreach ($i in 1..4) { $shell.SendKeys('{TAB}'); Start-Sleep -Milliseconds 30 }

  $shell.SendKeys($BrowserDisplayName)

  # Select the (first) search result to go to its details page.
  Start-Sleep -Milliseconds 100
  $shell.SendKeys('{TAB}  ')

  # Sleep a little so that the application-details page has a chance to open,
  # then click the 'Set Default` button.
  Start-Sleep -Milliseconds 500
  $shell.SendKeys(' ')

  # Close the window, unless requested not to.
  if (-not $KeepSettingsOpen) {
    $shell.SendKeys('%{F4}')
  }

  # Open a sample URL in the new default browser, if requested.
  if ($OpenSampleUrl) {
    Start-Process https://example.org
  }

}