Skip to content

Commit 02225ca

Browse files
rkeithhillTylerLeonhardt
authored andcommitted
Implementation of additional exe paths (#1270)
* Implementation of additional exe paths Fix #1243 * Address PR feedback
1 parent 9a363c7 commit 02225ca

File tree

5 files changed

+106
-27
lines changed

5 files changed

+106
-27
lines changed

package.json

+27
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,33 @@
400400
"isExecutable": true,
401401
"description": "Specifies the full path to a PowerShell executable. Changes the installation of PowerShell used for language and debugging services."
402402
},
403+
"powershell.powerShellAdditionalExePaths": {
404+
"type":"array",
405+
"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.",
406+
"isExecutable": true,
407+
"uniqueItems": true,
408+
"items": {
409+
"type": "object",
410+
"required":[
411+
"versionName",
412+
"exePath"
413+
],
414+
"properties": {
415+
"versionName": {
416+
"type":"string",
417+
"description": "Specifies the version name of this PowerShell executable. The version name can be referenced via the powershell.powerShellDefaultVersion setting."
418+
},
419+
"exePath": {
420+
"type":"string",
421+
"description": "Specifies the path to the PowerShell executable. Typically this is a path to a non-standard install location."
422+
}
423+
}
424+
}
425+
},
426+
"powershell.powerShellDefaultVersion": {
427+
"type":"string",
428+
"description": "Specifies the name of the PowerShell version used in the startup session when the extension loads e.g \"Windows PowerShell (x86)\" or \"PowerShell Core 6.0.2 (x64)\"."
429+
},
403430
"powershell.startAutomatically": {
404431
"type": "boolean",
405432
"default": true,

src/platform.ts

+27-16
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,13 @@ export function fixWindowsPowerShellPath(powerShellExePath: string, platformDeta
108108
return powerShellExePath;
109109
}
110110

111-
export function getAvailablePowerShellExes(platformDetails: IPlatformDetails): IPowerShellExeDetails[] {
111+
export function getAvailablePowerShellExes(
112+
platformDetails: IPlatformDetails,
113+
sessionSettings: Settings.ISettings | undefined): IPowerShellExeDetails[] {
112114

113115
let paths: IPowerShellExeDetails[] = [];
114116

115117
if (platformDetails.operatingSystem === OperatingSystem.Windows) {
116-
const psCoreInstallPath =
117-
(!platformDetails.isProcess64Bit ? process.env.ProgramW6432 : process.env.ProgramFiles) + "\\PowerShell";
118-
119118
if (platformDetails.isProcess64Bit) {
120119
paths.push({
121120
versionName: WindowsPowerShell64BitLabel,
@@ -140,33 +139,45 @@ export function getAvailablePowerShellExes(platformDetails: IPlatformDetails): I
140139
});
141140
}
142141

142+
const psCoreInstallPath =
143+
(!platformDetails.isProcess64Bit ? process.env.ProgramW6432 : process.env.ProgramFiles) + "\\PowerShell";
144+
143145
if (fs.existsSync(psCoreInstallPath)) {
146+
const arch = platformDetails.isProcess64Bit ? "(x64)" : "(x86)";
144147
const psCorePaths =
145148
fs.readdirSync(psCoreInstallPath)
146149
.map((item) => path.join(psCoreInstallPath, item))
147-
.filter((item) => fs.lstatSync(item).isDirectory())
148-
.map((item) => {
149-
let exePath = path.join(item, "pwsh.exe");
150-
if (!fs.existsSync(exePath)) {
151-
exePath = path.join(item, "powershell.exe");
152-
}
153-
154-
return {
155-
versionName: `PowerShell Core ${path.parse(item).base}`,
156-
exePath,
157-
};
158-
});
150+
.filter((item) => {
151+
const exePath = path.join(item, "pwsh.exe");
152+
return fs.lstatSync(item).isDirectory() && fs.existsSync(exePath);
153+
})
154+
.map((item) => ({
155+
versionName: `PowerShell Core ${path.parse(item).base} ${arch}`,
156+
exePath: path.join(item, "pwsh.exe"),
157+
}));
159158

160159
if (psCorePaths) {
161160
paths = paths.concat(psCorePaths);
162161
}
163162
}
164163
} else {
164+
// Handle Linux and macOS case
165165
paths.push({
166166
versionName: "PowerShell Core",
167167
exePath: this.getDefaultPowerShellPath(platformDetails),
168168
});
169169
}
170170

171+
// When unit testing, we don't have session settings to test so skip reading this setting
172+
if (sessionSettings) {
173+
// Add additional PowerShell paths as configured in settings
174+
for (const additionalPowerShellExePath of sessionSettings.powerShellAdditionalExePaths) {
175+
paths.push({
176+
versionName: additionalPowerShellExePath.versionName,
177+
exePath: additionalPowerShellExePath.exePath,
178+
});
179+
}
180+
}
181+
171182
return paths;
172183
}

src/session.ts

+40-10
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
getPlatformDetails, IPlatformDetails, OperatingSystem } from "./platform";
2727

2828
export enum SessionStatus {
29+
NeverStarted,
2930
NotStarted,
3031
Initializing,
3132
Running,
@@ -40,7 +41,7 @@ export class SessionManager implements Middleware {
4041
private hostVersion: string;
4142
private editorServicesArgs: string;
4243
private powerShellExePath: string = "";
43-
private sessionStatus: SessionStatus;
44+
private sessionStatus: SessionStatus = SessionStatus.NeverStarted;
4445
private suppressRestartPrompt: boolean;
4546
private focusConsoleOnExecute: boolean;
4647
private platformDetails: IPlatformDetails;
@@ -246,6 +247,7 @@ export class SessionManager implements Middleware {
246247
}
247248

248249
public getPowerShellExePath(): string {
250+
let powerShellExePath: string;
249251

250252
if (!this.sessionSettings.powerShellExePath &&
251253
this.sessionSettings.developer.powerShellExePath) {
@@ -280,11 +282,27 @@ export class SessionManager implements Middleware {
280282
});
281283
}
282284

285+
// If powershell.powerShellDefaultVersion specified, attempt to find the PowerShell exe path
286+
// of the version specified by the setting.
287+
if ((this.sessionStatus === SessionStatus.NeverStarted) && this.sessionSettings.powerShellDefaultVersion) {
288+
const powerShellExePaths = getAvailablePowerShellExes(this.platformDetails, this.sessionSettings);
289+
const powerShellDefaultVersion =
290+
powerShellExePaths.find((item) => item.versionName === this.sessionSettings.powerShellDefaultVersion);
291+
292+
if (powerShellDefaultVersion) {
293+
powerShellExePath = powerShellDefaultVersion.exePath;
294+
} else {
295+
this.log.writeWarning(
296+
`Could not find powerShellDefaultVersion: '${this.sessionSettings.powerShellDefaultVersion}'`);
297+
}
298+
}
299+
283300
// Is there a setting override for the PowerShell path?
284-
let powerShellExePath =
285-
(this.sessionSettings.powerShellExePath ||
286-
this.sessionSettings.developer.powerShellExePath ||
287-
"").trim();
301+
powerShellExePath =
302+
(powerShellExePath ||
303+
this.sessionSettings.powerShellExePath ||
304+
this.sessionSettings.developer.powerShellExePath ||
305+
"").trim();
288306

289307
// New versions of PS Core uninstall the previous version
290308
// so make sure the path stored in the settings exists.
@@ -718,12 +736,25 @@ export class SessionManager implements Middleware {
718736
private showSessionMenu() {
719737
let menuItems: SessionMenuItem[] = [];
720738

739+
const currentExePath = (this.powerShellExePath || "").toLowerCase();
740+
const availablePowerShellExes =
741+
getAvailablePowerShellExes(this.platformDetails, this.sessionSettings);
742+
721743
if (this.sessionStatus === SessionStatus.Running) {
744+
const currentPowerShellExe =
745+
availablePowerShellExes
746+
.find((item) => item.exePath.toLowerCase() === currentExePath);
747+
748+
const powerShellSessionName =
749+
currentPowerShellExe ?
750+
currentPowerShellExe.versionName :
751+
`PowerShell ${this.versionDetails.displayVersion} ` +
752+
`(${this.versionDetails.architecture}) ${this.versionDetails.edition} Edition ` +
753+
`[${this.versionDetails.version}]`;
754+
722755
menuItems = [
723756
new SessionMenuItem(
724-
`Current session: PowerShell ${this.versionDetails.displayVersion} ` +
725-
`(${this.versionDetails.architecture}) ${this.versionDetails.edition} Edition ` +
726-
`[${this.versionDetails.version}]`,
757+
`Current session: ${powerShellSessionName}`,
727758
() => { vscode.commands.executeCommand("PowerShell.ShowLogs"); }),
728759

729760
new SessionMenuItem(
@@ -738,9 +769,8 @@ export class SessionManager implements Middleware {
738769
];
739770
}
740771

741-
const currentExePath = (this.powerShellExePath || "").toLowerCase();
742772
const powerShellItems =
743-
getAvailablePowerShellExes(this.platformDetails)
773+
availablePowerShellExes
744774
.filter((item) => item.exePath.toLowerCase() !== currentExePath)
745775
.map((item) => {
746776
return new SessionMenuItem(

src/settings.ts

+11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ enum CodeFormattingPreset {
1414
Stroustrup,
1515
}
1616

17+
export interface IPowerShellAdditionalExePathSettings {
18+
versionName: string;
19+
exePath: string;
20+
}
21+
1722
export interface IBugReportingSettings {
1823
project: string;
1924
}
@@ -50,6 +55,8 @@ export interface IDeveloperSettings {
5055
}
5156

5257
export interface ISettings {
58+
powerShellAdditionalExePaths?: IPowerShellAdditionalExePathSettings[];
59+
powerShellDefaultVersion?: string;
5360
powerShellExePath?: string;
5461
startAutomatically?: boolean;
5562
useX86Host?: boolean;
@@ -115,6 +122,10 @@ export function load(): ISettings {
115122
return {
116123
startAutomatically:
117124
configuration.get<boolean>("startAutomatically", true),
125+
powerShellAdditionalExePaths:
126+
configuration.get<IPowerShellAdditionalExePathSettings[]>("powerShellAdditionalExePaths", undefined),
127+
powerShellDefaultVersion:
128+
configuration.get<string>("powerShellDefaultVersion", undefined),
118129
powerShellExePath:
119130
configuration.get<string>("powerShellExePath", undefined),
120131
useX86Host:

test/platform.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function checkAvailableWindowsPowerShellPaths(
2121

2222
// The system may return PowerShell Core paths so only
2323
// enumerate the first list items.
24-
const enumeratedPaths = platform.getAvailablePowerShellExes(platformDetails);
24+
const enumeratedPaths = platform.getAvailablePowerShellExes(platformDetails, undefined);
2525
for (let i; i < expectedPaths.length; i++) {
2626
assert.equal(enumeratedPaths[i], expectedPaths[i]);
2727
}

0 commit comments

Comments
 (0)