@@ -160,6 +160,10 @@ export class Executable {
160160 timeout : options . timeoutMs ,
161161 maxBuffer : options . maxBuffer ,
162162
163+ // Contrary to what the NodeJS typings imply, we must explicitly specify "utf8" here
164+ // if we want the result to be SpawnSyncReturns<string> instead of SpawnSyncReturns<Buffer>.
165+ encoding : 'utf8' ,
166+
163167 // NOTE: This is always false, because Rushell is recommended instead of relying on the OS shell.
164168 shell : false
165169 } as child_process . SpawnSyncOptionsWithStringEncoding ;
@@ -213,7 +217,10 @@ export class Executable {
213217 shellArgs . push ( '/s' ) ;
214218 // /C: Execute the following command and then exit immediately
215219 shellArgs . push ( '/c' ) ;
216- shellArgs . push ( resolvedPath ) ;
220+
221+ // If the path contains special charactrers (e.g. spaces), escape them so that
222+ // they don't get interpreted by the shell
223+ shellArgs . push ( Executable . _getEscapedForWindowsShell ( resolvedPath ) ) ;
217224 shellArgs . push ( ...args ) ;
218225
219226 return child_process . spawnSync ( shellPath , shellArgs , spawnOptions ) ;
@@ -412,6 +419,15 @@ export class Executable {
412419 } ;
413420 }
414421
422+ /**
423+ * Given an input string containing special symbol characters, this inserts the "^" escape
424+ * character to ensure the symbols are interpreted literally by the Windows shell.
425+ */
426+ private static _getEscapedForWindowsShell ( text : string ) : string {
427+ const escapableCharRegExp : RegExp = / [ % \^ & | < > ] / g;
428+ return text . replace ( escapableCharRegExp , ( value ) => '^' + value ) ;
429+ }
430+
415431 /**
416432 * Checks for characters that are unsafe to pass to a Windows batch file
417433 * due to the way that cmd.exe implements escaping.
0 commit comments