Skip to content

Commit c7f97c5

Browse files
Use powerShellDefaultVersion everywhere and stop using powerShellExePath
1 parent 517fe5c commit c7f97c5

File tree

5 files changed

+55
-168
lines changed

5 files changed

+55
-168
lines changed

package.json

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -499,12 +499,6 @@
499499
"default": [],
500500
"description": "Specify array of Modules to exclude from Command Explorer listing."
501501
},
502-
"powershell.powerShellExePath": {
503-
"type": "string",
504-
"default": "",
505-
"scope": "machine",
506-
"description": "Specifies the full path to a PowerShell executable. Changes the installation of PowerShell used for language and debugging services."
507-
},
508502
"powershell.powerShellAdditionalExePaths": {
509503
"type": "array",
510504
"description": "Specifies an array of versionName / exePath pairs where exePath points to a non-standard install location for PowerShell and versionName can be used to reference this path with the powershell.powerShellDefaultVersion setting.",
@@ -530,7 +524,7 @@
530524
},
531525
"powershell.powerShellDefaultVersion": {
532526
"type": "string",
533-
"description": "Specifies the PowerShell version name, as displayed by the 'PowerShell: Show Session Menu' command, used when the extension loads e.g \"Windows PowerShell (x86)\" or \"PowerShell Core 6 (x64)\"."
527+
"description": "Specifies the PowerShell version name, as displayed by the 'PowerShell: Show Session Menu' command, used when the extension loads e.g \"Windows PowerShell (x86)\" or \"PowerShell Core 6 (x64)\". You can specify additional PowerShell executables by using the \"powershell.powerShellAdditionalExePaths\" setting."
534528
},
535529
"powershell.promptToUpdatePowerShell": {
536530
"type": "boolean",

src/features/GenerateBugReport.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ ${tableHeader}\n${table};
113113

114114
private getRuntimeInfo() {
115115

116-
const powerShellExePath = this.sessionManager.getPowerShellExePath();
116+
const powerShellExePath = this.sessionManager.PowerShellExeDetails.exePath;
117117
const powerShellArgs = [
118118
"-NoProfile",
119119
"-Command",

src/session.ts

Lines changed: 42 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* Copyright (C) Microsoft Corporation. All rights reserved.
33
*--------------------------------------------------------*/
44

5-
import cp = require("child_process");
65
import fs = require("fs");
76
import net = require("net");
87
import path = require("path");
@@ -17,13 +16,13 @@ import Settings = require("./settings");
1716
import utils = require("./utils");
1817

1918
import {
20-
CloseAction, DocumentSelector, ErrorAction, Executable, LanguageClient, LanguageClientOptions,
21-
Middleware, NotificationType, RequestType, RequestType0,
19+
CloseAction, DocumentSelector, ErrorAction, LanguageClient, LanguageClientOptions,
20+
Middleware, NotificationType, RequestType0,
2221
ResolveCodeLensSignature, RevealOutputChannelOn, StreamInfo } from "vscode-languageclient";
2322

2423
import { GitHubReleaseInformation, InvokePowerShellUpdateCheck } from "./features/UpdatePowerShell";
2524
import {
26-
getPlatformDetails, IPlatformDetails,
25+
getPlatformDetails, IPlatformDetails, IPowerShellExeDetails,
2726
OperatingSystem, PowerShellExeFinder } from "./platform";
2827

2928
export enum SessionStatus {
@@ -37,9 +36,9 @@ export enum SessionStatus {
3736

3837
export class SessionManager implements Middleware {
3938
public HostVersion: string;
39+
public PowerShellExeDetails: IPowerShellExeDetails;
4040
private ShowSessionMenuCommandName = "PowerShell.ShowSessionMenu";
4141
private editorServicesArgs: string;
42-
private powerShellExePath: string = "";
4342
private sessionStatus: SessionStatus = SessionStatus.NeverStarted;
4443
private suppressRestartPrompt: boolean;
4544
private focusConsoleOnExecute: boolean;
@@ -119,15 +118,17 @@ export class SessionManager implements Middleware {
119118

120119
this.createStatusBarItem();
121120

121+
this.promptPowerShellExeSettingsCleanup();
122+
122123
try {
123-
this.powerShellExePath = this.getPowerShellExePath();
124+
this.PowerShellExeDetails = this.powershellExeFinder.getFirstAvailablePowerShellInstallation();
124125
} catch (e) {
125126
this.log.writeError(`Error occurred while searching for a PowerShell executable:\n${e}`);
126127
}
127128

128129
this.suppressRestartPrompt = false;
129130

130-
if (!this.powerShellExePath) {
131+
if (!this.PowerShellExeDetails) {
131132
const message = "Unable to find PowerShell."
132133
+ " Do you have PowerShell installed?"
133134
+ " You can also configure custom PowerShell installations"
@@ -230,7 +231,7 @@ export class SessionManager implements Middleware {
230231

231232
this.debugSessionProcess =
232233
new PowerShellProcess(
233-
this.powerShellExePath,
234+
this.PowerShellExeDetails.exePath,
234235
this.bundledModulesPath,
235236
"[TEMP] PowerShell Integrated Console",
236237
this.log,
@@ -241,51 +242,6 @@ export class SessionManager implements Middleware {
241242
return this.debugSessionProcess;
242243
}
243244

244-
public getPowerShellExePath(): string {
245-
if (!this.sessionSettings.powerShellExePath &&
246-
this.sessionSettings.developer.powerShellExePath) {
247-
// Show deprecation message with fix action.
248-
// We don't need to wait on this to complete
249-
// because we can finish gathering the configured
250-
// PowerShell path without the fix
251-
this.showExePathSettingDeprecationWarning();
252-
}
253-
254-
let powerShellExePath: string = this.getConfiguredPowerShellExePath().trim();
255-
256-
// New versions of PS Core uninstall the previous version
257-
// so make sure the path stored in the settings exists.
258-
if (!fs.existsSync(powerShellExePath)) {
259-
this.log.write(
260-
`Path specified by 'powerShellExePath' setting - '${powerShellExePath}' - not found, ` +
261-
"reverting to default PowerShell path.");
262-
powerShellExePath = "";
263-
}
264-
265-
if (powerShellExePath) {
266-
if (this.platformDetails.operatingSystem === OperatingSystem.Windows) {
267-
// Check the path bitness
268-
const fixedPath = this.powershellExeFinder.fixWindowsPowerShellPath(
269-
powerShellExePath);
270-
271-
if (fixedPath !== powerShellExePath) {
272-
// Show deprecation message with fix action.
273-
// We don't need to wait on this to complete
274-
// because we can finish gathering the configured
275-
// PowerShell path without the fix
276-
this.showBitnessPathFixWarning(fixedPath);
277-
powerShellExePath = fixedPath;
278-
}
279-
}
280-
281-
return this.resolvePowerShellPath(powerShellExePath);
282-
}
283-
284-
// No need to resolve this path, since the finder guarantees its existence
285-
const firstPowerShell = this.powershellExeFinder.getFirstAvailablePowerShellInstallation();
286-
return firstPowerShell && firstPowerShell.exePath || null;
287-
}
288-
289245
// ----- LanguageClient middleware methods -----
290246

291247
public resolveCodeLens(
@@ -331,64 +287,37 @@ export class SessionManager implements Middleware {
331287
return resolvedCodeLens;
332288
}
333289

334-
private async showExePathSettingDeprecationWarning(): Promise<void> {
335-
const choice: string = await vscode.window.showWarningMessage(
336-
"The 'powershell.developer.powerShellExePath' setting is deprecated, use " +
337-
"'powershell.powerShellExePath' instead.",
338-
"Fix Automatically");
339-
340-
if (!choice) {
341-
return;
342-
}
343-
344-
this.suppressRestartPrompt = true;
345-
await Settings.change("powerShellExePath", this.sessionSettings.developer.powerShellExePath, true);
346-
await Settings.change("developer.powerShellExePath", undefined, true);
347-
this.suppressRestartPrompt = false;
348-
}
349-
350-
private async showBitnessPathFixWarning(fixedPath: string): Promise<void> {
351-
const bitness = this.platformDetails.isOS64Bit ? "64" : "32";
290+
private async promptPowerShellExeSettingsCleanup() {
291+
if (this.sessionSettings.powerShellExePath) {
292+
let warningMessage = "The 'powerShell.powerShellExePath' setting is no longer used. ";
293+
warningMessage += this.sessionSettings.powerShellDefaultVersion
294+
? "We can automatically remove it for you."
295+
: "We can remove it from your settings and prompt you for which PowerShell you want to use.";
352296

353-
const choice = await vscode.window.showWarningMessage(
354-
`The specified PowerShell path is incorrect for ${bitness}-bit VS Code, using '${fixedPath}' instead.`,
355-
"Fix Setting Automatically");
297+
const choice = await vscode.window.showWarningMessage(warningMessage, "Let's do it!");
356298

357-
if (!choice) {
358-
return;
359-
}
299+
if (choice === "") {
300+
// They hit the 'x' to close the dialog.
301+
return;
302+
}
360303

361-
this.suppressRestartPrompt = true;
362-
await Settings.change("powerShellExePath", this.sessionSettings.developer.powerShellExePath, true);
363-
await Settings.change("developer.powerShellExePath", undefined, true);
364-
this.suppressRestartPrompt = false;
365-
}
304+
this.suppressRestartPrompt = true;
305+
try {
306+
await Settings.change("powerShellExePath", undefined, true);
366307

367-
private getConfiguredPowerShellExePath(): string {
368-
// If powershell.powerShellDefaultVersion specified, attempt to find the PowerShell exe path
369-
// of the version specified by the setting.
370-
if (this.sessionSettings.powerShellDefaultVersion && this.sessionStatus === SessionStatus.NeverStarted) {
371-
for (const pwshExe of this.powershellExeFinder.enumeratePowerShellInstallations()) {
372-
if (pwshExe.displayName === this.sessionSettings.powerShellDefaultVersion) {
373-
return pwshExe.exePath;
308+
// This has been deprecated for a while so siliently remove it if it's there.
309+
if (this.sessionSettings.developer.powerShellExePath) {
310+
await Settings.change("developer.powerShellExePath", undefined, true);
374311
}
312+
} finally {
313+
this.suppressRestartPrompt = false;
375314
}
376315

377-
// Default PowerShell version was configured but we didn't find it
378-
this.log.writeWarning(
379-
`Could not find powerShellDefaultVersion: '${this.sessionSettings.powerShellDefaultVersion}'`);
380-
}
381-
382-
if (this.sessionSettings.powerShellExePath) {
383-
return this.sessionSettings.powerShellExePath;
384-
}
385-
386-
if (this.sessionSettings.developer.powerShellExePath) {
387-
this.showExePathSettingDeprecationWarning();
388-
return this.sessionSettings.developer.powerShellExePath;
316+
// Show the session menu at the end if they don't have a PowerShellDefaultVersion.
317+
if (!this.sessionSettings.powerShellDefaultVersion) {
318+
await vscode.commands.executeCommand(this.ShowSessionMenuCommandName);
319+
}
389320
}
390-
391-
return "";
392321
}
393322

394323
private onConfigurationUpdated() {
@@ -398,11 +327,10 @@ export class SessionManager implements Middleware {
398327

399328
// Detect any setting changes that would affect the session
400329
if (!this.suppressRestartPrompt &&
401-
(settings.useX86Host !== this.sessionSettings.useX86Host ||
402-
settings.powerShellExePath.toLowerCase() !== this.sessionSettings.powerShellExePath.toLowerCase() ||
403-
(settings.developer.powerShellExePath ? settings.developer.powerShellExePath.toLowerCase() : null) !==
404-
(this.sessionSettings.developer.powerShellExePath
405-
? this.sessionSettings.developer.powerShellExePath.toLowerCase() : null) ||
330+
(settings.useX86Host !==
331+
this.sessionSettings.useX86Host ||
332+
settings.powerShellDefaultVersion.toLowerCase() !==
333+
this.sessionSettings.powerShellDefaultVersion.toLowerCase() ||
406334
settings.developer.editorServicesLogLevel.toLowerCase() !==
407335
this.sessionSettings.developer.editorServicesLogLevel.toLowerCase() ||
408336
settings.developer.bundledModulesPath.toLowerCase() !==
@@ -461,7 +389,7 @@ export class SessionManager implements Middleware {
461389

462390
this.languageServerProcess =
463391
new PowerShellProcess(
464-
this.powerShellExePath,
392+
this.PowerShellExeDetails.exePath,
465393
this.bundledModulesPath,
466394
"PowerShell Integrated Console",
467395
this.log,
@@ -691,63 +619,20 @@ export class SessionManager implements Middleware {
691619
SessionStatus.Failed);
692620
}
693621

694-
private changePowerShellExePath(exePath: string) {
622+
private changePowerShellDefaultVersion(exePath: IPowerShellExeDetails) {
695623
this.suppressRestartPrompt = true;
696624
Settings
697-
.change("powerShellExePath", exePath, true)
625+
.change("powerShellDefaultVersion", exePath.displayName, true)
698626
.then(() => this.restartSession());
699627
}
700628

701-
private resolvePowerShellPath(powerShellExePath: string): string {
702-
const resolvedPath = path.resolve(__dirname, powerShellExePath);
703-
704-
// If the path does not exist, show an error
705-
if (!utils.checkIfFileExists(resolvedPath)) {
706-
const pwshPath = resolvedPath || powerShellExePath;
707-
const pwshExeName = path.basename(pwshPath) || "PowerShell executable";
708-
709-
this.setSessionFailure(`${pwshExeName} cannot be found or is not accessible at path '${pwshPath}'`);
710-
711-
return null;
712-
}
713-
714-
return resolvedPath;
715-
}
716-
717-
private getPowerShellVersionLabel(): string {
718-
if (this.powerShellExePath) {
719-
const powerShellCommandLine = [
720-
this.powerShellExePath,
721-
"-NoProfile",
722-
"-NonInteractive",
723-
];
724-
725-
// Only add ExecutionPolicy param on Windows
726-
if (utils.isWindowsOS()) {
727-
powerShellCommandLine.push("-ExecutionPolicy", "Bypass");
728-
}
729-
730-
powerShellCommandLine.push(
731-
"-Command",
732-
"'$PSVersionTable | ConvertTo-Json'");
733-
734-
const powerShellOutput = cp.execSync(powerShellCommandLine.join(" "));
735-
const versionDetails = JSON.parse(powerShellOutput.toString());
736-
return versionDetails.PSVersion.Label;
737-
} else {
738-
// TODO: throw instead?
739-
return null;
740-
}
741-
}
742-
743629
private showSessionConsole(isExecute?: boolean) {
744630
if (this.languageServerProcess) {
745631
this.languageServerProcess.showConsole(isExecute && !this.focusConsoleOnExecute);
746632
}
747633
}
748634

749635
private showSessionMenu() {
750-
const currentExePath = (this.powerShellExePath || "").toLowerCase();
751636
const availablePowerShellExes = this.powershellExeFinder.getAllAvailablePowerShellInstallations();
752637

753638
let sessionText: string;
@@ -760,7 +645,7 @@ export class SessionManager implements Middleware {
760645
case SessionStatus.Stopping:
761646
const currentPowerShellExe =
762647
availablePowerShellExes
763-
.find((item) => item.exePath.toLowerCase() === currentExePath);
648+
.find((item) => item.displayName.toLowerCase() === this.PowerShellExeDetails.displayName);
764649

765650
const powerShellSessionName =
766651
currentPowerShellExe ?
@@ -782,11 +667,11 @@ export class SessionManager implements Middleware {
782667

783668
const powerShellItems =
784669
availablePowerShellExes
785-
.filter((item) => item.exePath.toLowerCase() !== currentExePath)
670+
.filter((item) => item.displayName.toLowerCase() !== this.PowerShellExeDetails.displayName)
786671
.map((item) => {
787672
return new SessionMenuItem(
788673
`Switch to: ${item.displayName}`,
789-
() => { this.changePowerShellExePath(item.exePath); });
674+
() => { this.changePowerShellDefaultVersion(item); });
790675
});
791676

792677
const menuItems: SessionMenuItem[] = [

src/settings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export interface IDebuggingSettings {
6969

7070
export interface IDeveloperSettings {
7171
featureFlags?: string[];
72+
// This setting is no longer used but is here to assist in cleaning up the users settings.
7273
powerShellExePath?: string;
7374
bundledModulesPath?: string;
7475
editorServicesLogLevel?: string;
@@ -79,6 +80,7 @@ export interface IDeveloperSettings {
7980
export interface ISettings {
8081
powerShellAdditionalExePaths?: IPowerShellAdditionalExePathSettings[];
8182
powerShellDefaultVersion?: string;
83+
// This setting is no longer used but is here to assist in cleaning up the users settings.
8284
powerShellExePath?: string;
8385
promptToUpdatePowerShell?: boolean;
8486
bundledModulesPath?: string;

test/settings.test.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*--------------------------------------------------------*/
44

55
import * as assert from "assert";
6+
import { IPowerShellExeDetails } from "../src/platform";
67
import Settings = require("../src/settings");
78

89
suite("Settings module", () => {
@@ -22,10 +23,15 @@ suite("Settings module", () => {
2223

2324
test("Settings that can only be user settings update correctly", async () => {
2425
// set to false means it's set as a workspace-level setting so this should throw.
25-
assert.rejects(async () => await Settings.change("powerShellExePath", "dummyPath", false));
26+
const psExeDetails = [{
27+
versionName: "My PowerShell",
28+
exePath: "dummyPath",
29+
}];
30+
31+
assert.rejects(async () => await Settings.change("powerShellAdditionalExePaths", psExeDetails, false));
2632

2733
// set to true means it's a user-level setting so this should not throw.
28-
await Settings.change("powerShellExePath", "dummyPath", true);
29-
assert.strictEqual(Settings.load().powerShellExePath, "dummyPath");
34+
await Settings.change("powerShellAdditionalExePaths", psExeDetails, true);
35+
assert.strictEqual(Settings.load().powerShellAdditionalExePaths[0].versionName, psExeDetails[0].versionName);
3036
});
3137
});

0 commit comments

Comments
 (0)