diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index f5d85a2f68e..1136a567c3f 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -335,7 +335,13 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { .inspect(key.substr(key.lastIndexOf('.') + 1)); return this._apiInspectConfigToPlain(setting); }; - return terminalEnvironment.getDefaultShell(fetchSetting, this._isWorkspaceShellAllowed, getDefaultShell(platform.platform)); + return terminalEnvironment.getDefaultShell( + fetchSetting, + this._isWorkspaceShellAllowed, + getDefaultShell(platform.platform), + process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'), + process.env.windir + ); } public async resolveTerminalRenderer(id: number): Promise { @@ -485,7 +491,14 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { .inspect(key.substr(key.lastIndexOf('.') + 1)); return this._apiInspectConfigToPlain(setting); }; - terminalEnvironment.mergeDefaultShellPathAndArgs(shellLaunchConfig, fetchSetting, isWorkspaceShellAllowed || false, getDefaultShell(platform.platform)); + terminalEnvironment.mergeDefaultShellPathAndArgs( + shellLaunchConfig, + fetchSetting, + isWorkspaceShellAllowed || false, + getDefaultShell(platform.platform), + process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'), + process.env.windir + ); } // Get the initial cwd diff --git a/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts index b009cbea51e..789b395e34b 100644 --- a/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/electron-browser/terminalTaskSystem.ts @@ -779,7 +779,7 @@ export class TerminalTaskSystem implements ITaskSystem { let originalCommand = task.command.name; if (isShellCommand) { shellLaunchConfig = { name: terminalName, executable: undefined, args: undefined, waitOnExit }; - this.terminalService.configHelper.mergeDefaultShellPathAndArgs(shellLaunchConfig, this.getDefaultShell(platform), platform); + this.terminalInstanceService.mergeDefaultShellPathAndArgs(shellLaunchConfig, this.getDefaultShell(platform), this.terminalService.configHelper, platform); let shellSpecified: boolean = false; let shellOptions: ShellConfiguration | undefined = task.command.options && task.command.options.shell; if (shellOptions) { diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 59c773a8f7b..b7648c67e3c 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -26,6 +26,10 @@ export interface ITerminalInstanceService { createWindowsShellHelper(shellProcessId: number, instance: ITerminalInstance, xterm: XTermTerminal): IWindowsShellHelper; createTerminalProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean): ITerminalChildProcess; getDefaultShell(p: Platform): string; + /** + * Merges the default shell path and args into the provided launch configuration + */ + mergeDefaultShellPathAndArgs(shell: IShellLaunchConfig, defaultShell: string, configHelper: ITerminalConfigHelper, platformOverride?: Platform): void; getMainProcessParentEnv(): Promise; } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts index 965f9de0e44..4935f3122e7 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts @@ -8,12 +8,11 @@ import * as platform from 'vs/base/common/platform'; import { EDITOR_FONT_DEFAULTS, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { ITerminalConfiguration, ITerminalFont, IShellLaunchConfig, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalConfiguration, ITerminalFont, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; import Severity from 'vs/base/common/severity'; import { Terminal as XTermTerminal } from 'xterm'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { IBrowserTerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { mergeDefaultShellPathAndArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; import { Emitter, Event } from 'vs/base/common/event'; const MINIMUM_FONT_SIZE = 6; @@ -232,11 +231,6 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { return !!isWorkspaceShellAllowed; } - public mergeDefaultShellPathAndArgs(shell: IShellLaunchConfig, defaultShell: string, platformOverride: platform.Platform = platform.platform): void { - const isWorkspaceShellAllowed = this.checkWorkspaceShellPermissions(platformOverride === platform.Platform.Windows ? platform.OperatingSystem.Windows : (platformOverride === platform.Platform.Mac ? platform.OperatingSystem.Macintosh : platform.OperatingSystem.Linux)); - mergeDefaultShellPathAndArgs(shell, (key) => this._workspaceConfigurationService.inspect(key), isWorkspaceShellAllowed, defaultShell, platformOverride); - } - private _toInteger(source: any, minimum: number, maximum: number, fallback: number): number { let r = parseInt(source, 10); if (isNaN(r)) { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts index eb28c172632..dbbb9313e12 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts @@ -55,4 +55,7 @@ export class TerminalInstanceService implements ITerminalInstanceService { public async getMainProcessParentEnv(): Promise { return {}; } + + public mergeDefaultShellPathAndArgs(): void { + } } \ No newline at end of file diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index f5c58368380..707c8068d26 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -161,7 +161,7 @@ export class TerminalProcessManager implements ITerminalProcessManager { private async _launchProcess(shellLaunchConfig: IShellLaunchConfig, cols: number, rows: number): Promise { if (!shellLaunchConfig.executable) { - this._configHelper.mergeDefaultShellPathAndArgs(shellLaunchConfig, this._terminalInstanceService.getDefaultShell(platform.platform)); + this._terminalInstanceService.mergeDefaultShellPathAndArgs(shellLaunchConfig, this._terminalInstanceService.getDefaultShell(platform.platform), this._configHelper); } const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file); diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index e700aef3e1b..78c89124183 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -9,7 +9,7 @@ import { RawContextKey, ContextKeyExpr, IContextKey } from 'vs/platform/contextk import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; import { FindReplaceState } from 'vs/editor/contrib/find/findState'; -import { Platform, OperatingSystem } from 'vs/base/common/platform'; +import { OperatingSystem } from 'vs/base/common/platform'; import { IOpenFileRequest } from 'vs/platform/windows/common/windows'; export const TERMINAL_PANEL_ID = 'workbench.panel.terminal'; @@ -114,10 +114,6 @@ export interface ITerminalConfigHelper { configFontIsMonospace(): boolean; getFont(): ITerminalFont; - /** - * Merges the default shell path and args into the provided launch configuration - */ - mergeDefaultShellPathAndArgs(shell: IShellLaunchConfig, defaultShell: string, platformOverride?: Platform): void; /** Sets whether a workspace shell configuration is allowed or not */ setWorkspaceShellAllowed(isAllowed: boolean): void; checkWorkspaceShellPermissions(osOverride?: OperatingSystem): boolean; diff --git a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts index 848164e0901..78a6f0e734f 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts @@ -166,6 +166,8 @@ export function getDefaultShell( fetchSetting: (key: string) => { user: string | string[] | undefined, value: string | string[] | undefined, default: string | string[] | undefined }, isWorkspaceShellAllowed: boolean, defaultShell: string, + isWoW64: boolean, + windir: string | undefined, platformOverride: platform.Platform = platform.platform ): string { const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux'; @@ -175,10 +177,10 @@ export function getDefaultShell( // Change Sysnative to System32 if the OS is Windows but NOT WoW64. It's // safe to assume that this was used by accident as Sysnative does not // exist and will break the terminal in non-WoW64 environments. - if ((platformOverride === platform.Platform.Windows) && !process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432') && process.env.windir) { - const sysnativePath = path.join(process.env.windir, 'Sysnative').toLowerCase(); + if ((platformOverride === platform.Platform.Windows) && !isWoW64 && windir) { + const sysnativePath = path.join(windir, 'Sysnative').toLowerCase(); if (executable && executable.toLowerCase().indexOf(sysnativePath) === 0) { - executable = path.join(process.env.windir, 'System32', executable.substr(sysnativePath.length)); + executable = path.join(windir, 'System32', executable.substr(sysnativePath.length)); } } @@ -193,7 +195,6 @@ export function getDefaultShell( function getDefaultShellArgs( fetchSetting: (key: string) => { user: string | string[] | undefined, value: string | string[] | undefined, default: string | string[] | undefined }, isWorkspaceShellAllowed: boolean, - defaultShell: string, platformOverride: platform.Platform = platform.platform ): string[] { const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux'; @@ -207,10 +208,12 @@ export function mergeDefaultShellPathAndArgs( fetchSetting: (key: string) => { user: string | string[] | undefined, value: string | string[] | undefined, default: string | string[] | undefined }, isWorkspaceShellAllowed: boolean, defaultShell: string, + isWoW64: boolean, + windir: string | undefined, platformOverride: platform.Platform = platform.platform ): void { - shell.executable = getDefaultShell(fetchSetting, isWorkspaceShellAllowed, defaultShell, platformOverride); - shell.args = getDefaultShellArgs(fetchSetting, isWorkspaceShellAllowed, defaultShell, platformOverride); + shell.executable = getDefaultShell(fetchSetting, isWorkspaceShellAllowed, defaultShell, isWoW64, windir, platformOverride); + shell.args = getDefaultShellArgs(fetchSetting, isWorkspaceShellAllowed, platformOverride); } export function createTerminalEnvironment( diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts index 885f01b4e4f..357bd5dc736 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { ITerminalInstance, IWindowsShellHelper, IShellLaunchConfig, ITerminalChildProcess } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalInstance, IWindowsShellHelper, IShellLaunchConfig, ITerminalChildProcess, ITerminalConfigHelper } from 'vs/workbench/contrib/terminal/common/terminal'; import { WindowsShellHelper } from 'vs/workbench/contrib/terminal/node/windowsShellHelper'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IProcessEnvironment, Platform, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; +import { IProcessEnvironment, Platform, isLinux, isMacintosh, isWindows, OperatingSystem, platform } from 'vs/base/common/platform'; import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess'; import { getDefaultShell } from 'vs/workbench/contrib/terminal/node/terminal'; import { Terminal as XTermTerminal } from 'xterm'; @@ -15,6 +15,8 @@ import { WebLinksAddon as XTermWebLinksAddon } from 'xterm-addon-web-links'; import { SearchAddon as XTermSearchAddon } from 'xterm-addon-search'; import { readFile } from 'vs/base/node/pfs'; import { basename } from 'vs/base/common/path'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { mergeDefaultShellPathAndArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; let Terminal: typeof XTermTerminal; let WebLinksAddon: typeof XTermWebLinksAddon; @@ -26,7 +28,8 @@ export class TerminalInstanceService implements ITerminalInstanceService { private _mainProcessParentEnv: IProcessEnvironment | undefined; constructor( - @IInstantiationService private readonly _instantiationService: IInstantiationService + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @IConfigurationService private readonly _configurationService: IConfigurationService ) { } @@ -63,6 +66,19 @@ export class TerminalInstanceService implements ITerminalInstanceService { return getDefaultShell(p); } + public mergeDefaultShellPathAndArgs(shell: IShellLaunchConfig, defaultShell: string, configHelper: ITerminalConfigHelper, platformOverride: Platform = platform): void { + const isWorkspaceShellAllowed = configHelper.checkWorkspaceShellPermissions(platformOverride === Platform.Windows ? OperatingSystem.Windows : (platformOverride === Platform.Mac ? OperatingSystem.Macintosh : OperatingSystem.Linux)); + mergeDefaultShellPathAndArgs( + shell, + (key) => this._configurationService.inspect(key), + isWorkspaceShellAllowed, + defaultShell, + process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'), + process.env.windir, + platformOverride + ); + } + public async getMainProcessParentEnv(): Promise { if (this._mainProcessParentEnv) { return this._mainProcessParentEnv; diff --git a/src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts index 2ed2188c6d0..eea75ac373d 100644 --- a/src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts +++ b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts @@ -30,6 +30,9 @@ class TestXterm { } class MockTerminalInstanceService implements ITerminalInstanceService { + mergeDefaultShellPathAndArgs(): void { + throw new Error('Method not implemented.'); + } _serviceBrand: any; getXtermConstructor(): Promise { throw new Error('Method not implemented.');