diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 390317f4391..9fdb90b0295 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -9,7 +9,7 @@ import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMai import { IWindowOpenable } from 'vs/platform/windows/common/windows'; import { OpenContext } from 'vs/platform/windows/node/window'; import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; -import { getShellEnvironment } from 'vs/code/node/shellEnv'; +import { resolveShellEnv } from 'vs/code/node/shellEnv'; import { IUpdateService } from 'vs/platform/update/common/update'; import { UpdateChannel } from 'vs/platform/update/electron-main/updateIpc'; import { Server as ElectronIPCServer } from 'vs/base/parts/ipc/electron-main/ipc.electron-main'; @@ -84,6 +84,7 @@ import { EncryptionMainService, IEncryptionMainService } from 'vs/platform/encry import { ActiveWindowManager } from 'vs/platform/windows/common/windowTracker'; import { IKeyboardLayoutMainService, KeyboardLayoutMainService } from 'vs/platform/keyboardLayout/electron-main/keyboardLayoutMainService'; import { toErrorMessage } from 'vs/base/common/errorMessage'; +import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; export class CodeApplication extends Disposable { private windowsMainService: IWindowsMainService | undefined; @@ -283,7 +284,24 @@ export class CodeApplication extends Disposable { }, 10000); try { - const shellEnv = await getShellEnvironment(this.logService, this.environmentService); + + // Prefer to use the args and env from the target window + // when resolving the shell env. It is possible that + // a first window was opened from the UI but a second + // from the CLI and that has implications for wether to + // resolve the shell environment or not. + let args: NativeParsedArgs; + let env: NodeJS.ProcessEnv; + if (window?.config) { + args = window.config; + env = { ...process.env, ...window.config.userEnv }; + } else { + args = this.environmentService.args; + env = process.env; + } + + // Resolve shell env + const shellEnv = await resolveShellEnv(this.logService, args, env); acceptShellEnv(shellEnv); } catch (error) { window?.sendWhenReady('vscode:showShellEnvError', toErrorMessage(error)); // notify inside window if we have one @@ -368,7 +386,7 @@ export class CodeApplication extends Disposable { }); this.lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen).then(() => { this._register(new RunOnceScheduler(async () => { - sharedProcess.spawn(await getShellEnvironment(this.logService, this.environmentService)); + sharedProcess.spawn(await resolveShellEnv(this.logService, this.environmentService.args, process.env)); }, 3000)).schedule(); }); @@ -825,8 +843,8 @@ export class CodeApplication extends Disposable { updateService.initialize(); } - // Start to fetch shell environment after window has opened - getShellEnvironment(this.logService, this.environmentService); + // Start to fetch shell environment (if needed) after window has opened + resolveShellEnv(this.logService, this.environmentService.args, process.env); // If enable-crash-reporter argv is undefined then this is a fresh start, // based on telemetry.enableCrashreporter settings, generate a UUID which diff --git a/src/vs/code/node/shellEnv.ts b/src/vs/code/node/shellEnv.ts index d1dd0bc6dfb..a7422f5357a 100644 --- a/src/vs/code/node/shellEnv.ts +++ b/src/vs/code/node/shellEnv.ts @@ -7,9 +7,55 @@ import { spawn } from 'child_process'; import { generateUuid } from 'vs/base/common/uuid'; import { isWindows } from 'vs/base/common/platform'; import { ILogService } from 'vs/platform/log/common/log'; -import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; +import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; -function getUnixShellEnvironment(logService: ILogService): Promise { +/** + * We need to get the environment from a user's shell. + * This should only be done when Code itself is not launched + * from within a shell. + */ +export async function resolveShellEnv(logService: ILogService, args: NativeParsedArgs, env: NodeJS.ProcessEnv): Promise { + + // Skip if --force-disable-user-env + if (args['force-disable-user-env']) { + logService.trace('resolveShellEnv(): skipped (--force-disable-user-env)'); + + return {}; + } + + // Skip on windows + else if (isWindows) { + logService.trace('resolveShellEnv(): skipped (Windows)'); + + return {}; + } + + // Skip if running from CLI already + else if (env['VSCODE_CLI'] === '1' && !args['force-user-env']) { + logService.trace('resolveShellEnv(): skipped (VSCODE_CLI is set)'); + + return {}; + } + + // Otherwise resolve (macOS, Linux) + else { + if (env['VSCODE_CLI'] === '1') { + logService.trace('resolveShellEnv(): running (--force-user-env)'); + } else { + logService.trace('resolveShellEnv(): running (macOS/Linux)'); + } + + if (!unixShellEnvPromise) { + unixShellEnvPromise = doResolveUnixShellEnv(logService); + } + + return unixShellEnvPromise; + } +} + +let unixShellEnvPromise: Promise | undefined = undefined; + +function doResolveUnixShellEnv(logService: ILogService): Promise { const promise = new Promise((resolve, reject) => { const runAsNode = process.env['ELECTRON_RUN_AS_NODE']; logService.trace('getUnixShellEnvironment#runAsNode', runAsNode); @@ -81,34 +127,3 @@ function getUnixShellEnvironment(logService: ILogService): Promise ({})); } - -let shellEnvPromise: Promise | undefined = undefined; - -/** - * We need to get the environment from a user's shell. - * This should only be done when Code itself is not launched - * from within a shell. - */ -export function getShellEnvironment(logService: ILogService, environmentService: INativeEnvironmentService): Promise { - if (!shellEnvPromise) { - if (environmentService.args['force-disable-user-env']) { - logService.trace('getShellEnvironment(): skipped (--force-disable-user-env)'); - shellEnvPromise = Promise.resolve({}); - } else if (isWindows) { - logService.trace('getShellEnvironment(): skipped (Windows)'); - shellEnvPromise = Promise.resolve({}); - } else if (process.env['VSCODE_CLI'] === '1' && !environmentService.args['force-user-env']) { - logService.trace('getShellEnvironment(): skipped (VSCODE_CLI is set)'); - shellEnvPromise = Promise.resolve({}); - } else { - if (process.env['VSCODE_CLI'] === '1') { - logService.trace('getShellEnvironment(): running (--force-user-env)'); - } else { - logService.trace('getShellEnvironment(): running (macOS/Linux)'); - } - shellEnvPromise = getUnixShellEnvironment(logService); - } - } - - return shellEnvPromise; -}