From 6322d0e97efd71e5894f58b028266739c334f4ff Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Thu, 2 Jan 2020 15:44:31 -0800 Subject: [PATCH 1/6] Add -Login startup option --- package.json | 5 +++++ src/session.ts | 17 +++++++++++++++++ src/settings.ts | 1 + 3 files changed, 23 insertions(+) diff --git a/package.json b/package.json index 0931fb3fb9..a36236f3ef 100644 --- a/package.json +++ b/package.json @@ -550,6 +550,11 @@ "description": "Specifies whether you should be prompted to update your version of PowerShell.", "default": true }, + "powershell.startAsLoginShell": { + "type": "boolean", + "default": false, + "description": "Starts the PowerShell extension's underlying PowerShell process as a login shell, if applicable." + }, "powershell.startAutomatically": { "type": "boolean", "default": true, diff --git a/src/session.ts b/src/session.ts index 5a2cd3a6ac..fa3dd1c1a9 100644 --- a/src/session.ts +++ b/src/session.ts @@ -2,6 +2,7 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ +import * as cp from "child_process"; import fs = require("fs"); import net = require("net"); import path = require("path"); @@ -187,6 +188,12 @@ export class SessionManager implements Middleware { `-BundledModulesPath '${PowerShellProcess.escapeSingleQuotes(this.bundledModulesPath)}' ` + `-EnableConsoleRepl `; + if (this.sessionSettings.startAsLoginShell + && this.platformDetails.operatingSystem !== OperatingSystem.Windows + && this.isLoginShell(this.PowerShellExeDetails.exePath)) { + this.editorServicesArgs = "-Login " + this.editorServicesArgs; + } + if (this.sessionSettings.developer.editorServicesWaitForDebugger) { this.editorServicesArgs += "-WaitForDebugger "; } @@ -719,6 +726,16 @@ export class SessionManager implements Middleware { .showQuickPick(menuItems) .then((selectedItem) => { selectedItem.callback(); }); } + + private isLoginShell(pwshPath: string): boolean { + try { + cp.execFileSync(pwshPath, ["-Login", "-NoProfile", "-NoLogo", "-Command", "0"]); + } catch { + return false; + } + + return true; + } } class SessionMenuItem implements vscode.QuickPickItem { diff --git a/src/settings.ts b/src/settings.ts index d57a9cedf7..bee40e8694 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -82,6 +82,7 @@ export interface ISettings { powerShellExePath?: string; promptToUpdatePowerShell?: boolean; bundledModulesPath?: string; + startAsLoginShell?: boolean; startAutomatically?: boolean; useX86Host?: boolean; enableProfileLoading?: boolean; From c47e47c413c55bc667621dcd635308178a316914 Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Thu, 2 Jan 2020 15:46:59 -0800 Subject: [PATCH 2/6] Improve dummy command --- src/session.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/session.ts b/src/session.ts index fa3dd1c1a9..5280f64647 100644 --- a/src/session.ts +++ b/src/session.ts @@ -729,7 +729,7 @@ export class SessionManager implements Middleware { private isLoginShell(pwshPath: string): boolean { try { - cp.execFileSync(pwshPath, ["-Login", "-NoProfile", "-NoLogo", "-Command", "0"]); + cp.execFileSync(pwshPath, ["-Login", "-NoProfile", "-NoLogo", "-Command", "exit 0"]); } catch { return false; } From 8a4b8777384209dd689edca81f3fb0c1e6ada1b7 Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Fri, 3 Jan 2020 10:56:55 -0800 Subject: [PATCH 3/6] Add explanatory comment --- src/session.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/session.ts b/src/session.ts index 5280f64647..0b611c4094 100644 --- a/src/session.ts +++ b/src/session.ts @@ -729,6 +729,10 @@ export class SessionManager implements Middleware { private isLoginShell(pwshPath: string): boolean { try { + // We can't know what version of PowerShell we have without running it + // So we try to start PowerShell with -Login + // If it exits successfully, we return true + // If it exits unsuccessfully, node throws, we catch, and return false cp.execFileSync(pwshPath, ["-Login", "-NoProfile", "-NoLogo", "-Command", "exit 0"]); } catch { return false; From be348b2e57f24975e47075ea681f9ca6aeb5289a Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Thu, 9 Jan 2020 18:14:38 -0800 Subject: [PATCH 4/6] switch to .osx & .linux and code clean up --- package.json | 12 +++++------ src/process.ts | 55 ++++++++++++++++++++++++++++--------------------- src/session.ts | 20 ------------------ src/settings.ts | 21 ++++++++++++++++--- 4 files changed, 55 insertions(+), 53 deletions(-) diff --git a/package.json b/package.json index a36236f3ef..9abea534e6 100644 --- a/package.json +++ b/package.json @@ -550,7 +550,12 @@ "description": "Specifies whether you should be prompted to update your version of PowerShell.", "default": true }, - "powershell.startAsLoginShell": { + "powershell.startAsLoginShell.osx": { + "type": "boolean", + "default": true, + "description": "Starts the PowerShell extension's underlying PowerShell process as a login shell, if applicable." + }, + "powershell.startAsLoginShell.linux": { "type": "boolean", "default": false, "description": "Starts the PowerShell extension's underlying PowerShell process as a login shell, if applicable." @@ -740,11 +745,6 @@ "type": "array", "default": null, "description": "An array of strings that enable experimental features in the PowerShell extension." - }, - "powershell.developer.powerShellExeIsWindowsDevBuild": { - "type": "boolean", - "default": false, - "description": "Indicates that the powerShellExePath points to a developer build of Windows PowerShell and configures it for development." } } }, diff --git a/src/process.ts b/src/process.ts index aefcd451f1..1b78426efc 100644 --- a/src/process.ts +++ b/src/process.ts @@ -63,10 +63,19 @@ export class PowerShellProcess { this.startArgs += "-UseLegacyReadLine"; } - const powerShellArgs = [ - "-NoProfile", - "-NonInteractive", - ]; + const powerShellArgs = []; + + const checkLoginShell: boolean = + (utils.isMacOS && this.sessionSettings.startAsLoginShell.osx) + || (utils.isLinux && this.sessionSettings.startAsLoginShell.linux); + + if (checkLoginShell && this.isLoginShell(this.exePath)) { + // This MUST be the first argument. + powerShellArgs.push("-Login"); + } + + powerShellArgs.push("-NoProfile"); + powerShellArgs.push("-NonInteractive"); // Only add ExecutionPolicy param on Windows if (utils.isWindows) { @@ -88,27 +97,11 @@ export class PowerShellProcess { Buffer.from(startEditorServices, "utf16le").toString("base64")); } - let powerShellExePath = this.exePath; - - if (this.sessionSettings.developer.powerShellExeIsWindowsDevBuild) { - // Windows PowerShell development builds need the DEVPATH environment - // variable set to the folder where development binaries are held - - // NOTE: This batch file approach is needed temporarily until VS Code's - // createTerminal API gets an argument for setting environment variables - // on the launched process. - const batScriptPath = path.resolve(__dirname, "../../sessions/powershell.bat"); - fs.writeFileSync( - batScriptPath, - `@set DEVPATH=${path.dirname(powerShellExePath)}\r\n@${powerShellExePath} %*`); - - powerShellExePath = batScriptPath; - } - this.log.write( "Language server starting --", - " exe: " + powerShellExePath, - " args: " + startEditorServices); + " PowerShell executable: " + this.exePath, + " PowerShell args: " + powerShellArgs.join(" "), + " PowerShell Editor Services args: " + startEditorServices); // Make sure no old session file exists utils.deleteSessionFile(this.sessionFilePath); @@ -117,7 +110,7 @@ export class PowerShellProcess { this.consoleTerminal = vscode.window.createTerminal( this.title, - powerShellExePath, + this.exePath, powerShellArgs); if (this.sessionSettings.integratedConsole.showOnStartup) { @@ -178,4 +171,18 @@ export class PowerShellProcess { this.consoleTerminal = undefined; } } + + private isLoginShell(pwshPath: string): boolean { + try { + // We can't know what version of PowerShell we have without running it + // So we try to start PowerShell with -Login + // If it exits successfully, we return true + // If it exits unsuccessfully, node throws, we catch, and return false + cp.execFileSync(pwshPath, ["-Login", "-NoProfile", "-NoLogo", "-Command", "exit 0"]); + } catch { + return false; + } + + return true; + } } diff --git a/src/session.ts b/src/session.ts index 0b611c4094..f7debfeda5 100644 --- a/src/session.ts +++ b/src/session.ts @@ -188,12 +188,6 @@ export class SessionManager implements Middleware { `-BundledModulesPath '${PowerShellProcess.escapeSingleQuotes(this.bundledModulesPath)}' ` + `-EnableConsoleRepl `; - if (this.sessionSettings.startAsLoginShell - && this.platformDetails.operatingSystem !== OperatingSystem.Windows - && this.isLoginShell(this.PowerShellExeDetails.exePath)) { - this.editorServicesArgs = "-Login " + this.editorServicesArgs; - } - if (this.sessionSettings.developer.editorServicesWaitForDebugger) { this.editorServicesArgs += "-WaitForDebugger "; } @@ -726,20 +720,6 @@ export class SessionManager implements Middleware { .showQuickPick(menuItems) .then((selectedItem) => { selectedItem.callback(); }); } - - private isLoginShell(pwshPath: string): boolean { - try { - // We can't know what version of PowerShell we have without running it - // So we try to start PowerShell with -Login - // If it exits successfully, we return true - // If it exits unsuccessfully, node throws, we catch, and return false - cp.execFileSync(pwshPath, ["-Login", "-NoProfile", "-NoLogo", "-Command", "exit 0"]); - } catch { - return false; - } - - return true; - } } class SessionMenuItem implements vscode.QuickPickItem { diff --git a/src/settings.ts b/src/settings.ts index bee40e8694..090c9e08b5 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -72,7 +72,6 @@ export interface IDeveloperSettings { bundledModulesPath?: string; editorServicesLogLevel?: string; editorServicesWaitForDebugger?: boolean; - powerShellExeIsWindowsDevBuild?: boolean; } export interface ISettings { @@ -82,7 +81,7 @@ export interface ISettings { powerShellExePath?: string; promptToUpdatePowerShell?: boolean; bundledModulesPath?: string; - startAsLoginShell?: boolean; + startAsLoginShell?: IStartAsLoginShellSettings; startAutomatically?: boolean; useX86Host?: boolean; enableProfileLoading?: boolean; @@ -97,6 +96,11 @@ export interface ISettings { sideBar?: ISideBarSettings; } +export interface IStartAsLoginShellSettings { + osx?: boolean; + linux?: boolean; +} + export interface IIntegratedConsoleSettings { showOnStartup?: boolean; focusConsoleOnExecute?: boolean; @@ -131,7 +135,6 @@ export function load(): ISettings { bundledModulesPath: "../../../PowerShellEditorServices/module", editorServicesLogLevel: "Normal", editorServicesWaitForDebugger: false, - powerShellExeIsWindowsDevBuild: false, }; const defaultCodeFoldingSettings: ICodeFoldingSettings = { @@ -157,6 +160,11 @@ export function load(): ISettings { useCorrectCasing: false, }; + const defaultStartAsLoginShellSettings: IStartAsLoginShellSettings = { + osx: true, + linux: false, + }; + const defaultIntegratedConsoleSettings: IIntegratedConsoleSettings = { showOnStartup: true, focusConsoleOnExecute: true, @@ -203,6 +211,13 @@ export function load(): ISettings { configuration.get("bugReporting", defaultBugReportingSettings), sideBar: configuration.get("sideBar", defaultSideBarSettings), + startAsLoginShell: + // tslint:disable-next-line + // We follow the same convention as VS Code - https://github.com/microsoft/vscode/blob/ff00badd955d6cfcb8eab5f25f3edc86b762f49f/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts#L105-L107 + // "Unlike on Linux, ~/.profile is not sourced when logging into a macOS session. This + // is the reason terminals on macOS typically run login shells by default which set up + // the environment. See http://unix.stackexchange.com/a/119675/115410" + configuration.get("startAsLoginShell", defaultStartAsLoginShellSettings), }; } From 160ce8085971ac40e4f87314bb0e81ae7c58247b Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Thu, 9 Jan 2020 18:15:54 -0800 Subject: [PATCH 5/6] remove import --- src/session.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/session.ts b/src/session.ts index f7debfeda5..5a2cd3a6ac 100644 --- a/src/session.ts +++ b/src/session.ts @@ -2,7 +2,6 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import * as cp from "child_process"; import fs = require("fs"); import net = require("net"); import path = require("path"); From 87b6c91a37a13dfcef09937d82e7f40cbf32c623 Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Fri, 10 Jan 2020 11:39:43 -0800 Subject: [PATCH 6/6] rob's feedback --- src/process.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/process.ts b/src/process.ts index 1b78426efc..3138c6cfdb 100644 --- a/src/process.ts +++ b/src/process.ts @@ -65,11 +65,11 @@ export class PowerShellProcess { const powerShellArgs = []; - const checkLoginShell: boolean = + const useLoginShell: boolean = (utils.isMacOS && this.sessionSettings.startAsLoginShell.osx) || (utils.isLinux && this.sessionSettings.startAsLoginShell.linux); - if (checkLoginShell && this.isLoginShell(this.exePath)) { + if (useLoginShell && this.isLoginShell(this.exePath)) { // This MUST be the first argument. powerShellArgs.push("-Login"); }