@@ -3,7 +3,6 @@ const {promisify} = require('util');
3
3
const path = require ( 'path' ) ;
4
4
const childProcess = require ( 'child_process' ) ;
5
5
const fs = require ( 'fs' ) ;
6
- const url = require ( 'url' ) ;
7
6
const isWsl = require ( 'is-wsl' ) ;
8
7
const isDocker = require ( 'is-docker' ) ;
9
8
@@ -28,30 +27,19 @@ module.exports = async (target, options) => {
28
27
options = {
29
28
wait : false ,
30
29
background : false ,
31
- url : false ,
32
30
allowNonzeroExitCode : false ,
33
31
...options
34
32
} ;
35
33
36
34
let command ;
35
+ let app ;
37
36
let appArguments = [ ] ;
38
37
const cliArguments = [ ] ;
39
38
const childProcessOptions = { } ;
40
39
41
40
if ( Array . isArray ( options . app ) ) {
42
41
appArguments = options . app . slice ( 1 ) ;
43
- options . app = options . app [ 0 ] ;
44
- }
45
-
46
- // Encodes the target as if it were an URL. Especially useful to get
47
- // double-quotes through the “double-quotes on Windows caveat”, but it
48
- // can be used on any platform.
49
- if ( options . url ) {
50
- target = new url . URL ( target ) . href ;
51
-
52
- if ( isWsl ) {
53
- target = target . replace ( / & / g, '^&' ) ;
54
- }
42
+ app = options . app [ 0 ] ;
55
43
}
56
44
57
45
if ( process . platform === 'darwin' ) {
@@ -65,49 +53,53 @@ module.exports = async (target, options) => {
65
53
cliArguments . push ( '--background' ) ;
66
54
}
67
55
68
- if ( options . app ) {
69
- cliArguments . push ( '-a' , options . app ) ;
56
+ if ( app ) {
57
+ cliArguments . push ( '-a' , app ) ;
70
58
}
71
59
} else if ( process . platform === 'win32' || ( isWsl && ! isDocker ( ) ) ) {
72
- command = 'cmd' + ( isWsl ? '.exe' : '' ) ;
73
- cliArguments . push ( '/s' , '/c' , 'start' , '""' , '/b' ) ;
60
+ command = 'powershell' + ( isWsl ? '.exe' : '' ) ;
61
+ cliArguments . push (
62
+ '-NoProfile' ,
63
+ '-NonInteractive' ,
64
+ '–ExecutionPolicy' ,
65
+ 'Bypass' ,
66
+ '-EncodedCommand'
67
+ ) ;
74
68
75
69
if ( ! isWsl ) {
76
- // Always quoting target allows for URLs/paths to have spaces and unmarked characters, as `cmd.exe` will
77
- // interpret them as plain text to be forwarded as one unique argument. Enabling `windowsVerbatimArguments`
78
- // disables Node.js's default quotes and escapes handling (https://git.io/fjdem).
79
- // References:
80
- // - Issues #17, #44, #55, #77, #101, #115
81
- // - Pull requests: #74, #98
82
- //
83
- // As a result, all double-quotes are stripped from the `target` and do not get to your desired destination.
84
- target = `"${ target } "` ;
85
70
childProcessOptions . windowsVerbatimArguments = true ;
86
-
87
- if ( options . app ) {
88
- options . app = `"${ options . app } "` ;
89
- }
90
71
}
91
72
73
+ const encodedArguments = [ 'Start' ] ;
74
+
92
75
if ( options . wait ) {
93
- cliArguments . push ( '/wait ' ) ;
76
+ encodedArguments . push ( '-Wait ' ) ;
94
77
}
95
78
96
- if ( options . app ) {
97
- if ( isWsl && options . app . startsWith ( '/mnt/' ) ) {
98
- const windowsPath = await wslToWindowsPath ( options . app ) ;
99
- options . app = windowsPath ;
79
+ if ( app ) {
80
+ if ( isWsl && app . startsWith ( '/mnt/' ) ) {
81
+ const windowsPath = await wslToWindowsPath ( app ) ;
82
+ app = windowsPath ;
100
83
}
101
84
102
- cliArguments . push ( options . app ) ;
85
+ // Double quote with double quotes to ensure the inner quotes are passed through.
86
+ // Inner quotes are delimited for PowerShell interpretation with backticks.
87
+ encodedArguments . push ( `"\`"${ app } \`""` , '-ArgumentList' ) ;
88
+ appArguments . unshift ( target ) ;
89
+ } else {
90
+ encodedArguments . push ( `"\`"${ target } \`""` ) ;
103
91
}
104
92
105
93
if ( appArguments . length > 0 ) {
106
- cliArguments . push ( ...appArguments ) ;
94
+ appArguments = appArguments . map ( arg => `"\`"${ arg } \`""` ) ;
95
+ encodedArguments . push ( appArguments . join ( ',' ) ) ;
107
96
}
97
+
98
+ // Using Base64-encoded command, accepted by PowerShell, to allow special characters.
99
+ target = Buffer . from ( encodedArguments . join ( ' ' ) , 'utf16le' ) . toString ( 'base64' ) ;
108
100
} else {
109
- if ( options . app ) {
110
- command = options . app ;
101
+ if ( app ) {
102
+ command = app ;
111
103
} else {
112
104
// When bundled by Webpack, there's no actual package file path and no local `xdg-open`.
113
105
const isBundled = ! __dirname || __dirname === '/' ;
0 commit comments