Skip to content

Commit 6187a82

Browse files
Fix detection of Windows default browser from WSL (#358)
Co-authored-by: Sindre Sorhus <[email protected]>
1 parent 31b71c5 commit 6187a82

File tree

1 file changed

+50
-4
lines changed

1 file changed

+50
-4
lines changed

index.js

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ import process from 'node:process';
22
import {Buffer} from 'node:buffer';
33
import path from 'node:path';
44
import {fileURLToPath} from 'node:url';
5+
import util from 'node:util';
56
import childProcess from 'node:child_process';
67
import fs, {constants as fsConstants} from 'node:fs/promises';
78
import isWsl from 'is-wsl';
89
import defineLazyProperty from 'define-lazy-prop';
910
import defaultBrowser from 'default-browser';
1011
import isInsideContainer from 'is-inside-container';
1112

13+
const execFile = util.promisify(childProcess.execFile);
14+
1215
// Path to included `xdg-open`.
1316
const __dirname = path.dirname(fileURLToPath(import.meta.url));
1417
const localXdgOpenPath = path.join(__dirname, 'xdg-open');
@@ -60,6 +63,51 @@ const getWslDrivesMountPoint = (() => {
6063
};
6164
})();
6265

66+
/**
67+
Get the PowerShell executable path in WSL environment.
68+
69+
@returns {Promise<string>} The absolute path to the PowerShell executable in WSL.
70+
*/
71+
const getPowershellPathFromWsl = async () => {
72+
const mountPoint = await getWslDrivesMountPoint();
73+
return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
74+
};
75+
76+
/**
77+
Get the default browser name in Windows from WSL.
78+
79+
@returns {Promise<string>} Browser name.
80+
*/
81+
async function getWindowsDefaultBrowserFromWsl() {
82+
const powershellPath = await getPowershellPathFromWsl();
83+
const rawCommand = '(Get-ItemProperty -Path "HKCU:\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice").ProgId';
84+
const encodedCommand = Buffer.from(rawCommand, 'utf16le').toString('base64');
85+
86+
const {stdout} = await execFile(
87+
powershellPath,
88+
[
89+
'-NoProfile',
90+
'-NonInteractive',
91+
'-ExecutionPolicy',
92+
'Bypass',
93+
'-EncodedCommand',
94+
encodedCommand,
95+
],
96+
{encoding: 'utf8'},
97+
);
98+
99+
const progId = stdout.trim();
100+
101+
// Map ProgId to browser IDs
102+
const browserMap = {
103+
ChromeHTML: 'com.google.chrome',
104+
MSEdgeHTM: 'com.microsoft.edge',
105+
FirefoxURL: 'org.mozilla.firefox',
106+
};
107+
108+
return browserMap[progId] ? {id: browserMap[progId]} : {};
109+
}
110+
63111
const pTryEach = async (array, mapper) => {
64112
let latestError;
65113

@@ -123,7 +171,7 @@ const baseOpen = async options => {
123171
edge: '--inPrivate',
124172
};
125173

126-
const browser = await defaultBrowser();
174+
const browser = isWsl ? await getWindowsDefaultBrowserFromWsl() : await defaultBrowser();
127175
if (browser.id in ids) {
128176
const browserName = ids[browser.id];
129177

@@ -166,10 +214,8 @@ const baseOpen = async options => {
166214
cliArguments.push('-a', app);
167215
}
168216
} else if (platform === 'win32' || (isWsl && !isInsideContainer() && !app)) {
169-
const mountPoint = await getWslDrivesMountPoint();
170-
171217
command = isWsl
172-
? `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`
218+
? await getPowershellPathFromWsl()
173219
: `${process.env.SYSTEMROOT || process.env.windir || 'C:\\Windows'}\\System32\\WindowsPowerShell\\v1.0\\powershell`;
174220

175221
cliArguments.push(

0 commit comments

Comments
 (0)