Skip to content

Commit 9d7b0ef

Browse files
committed
Enhance additionalPowerShellExes setting
Now the warning that's emitted when an additional PowerShell executable isn't found can be suppressed with a setting. If the setting's value has single or double quotes, it handles it. If the executable name wasn't appended, it handles it. Smarter!
1 parent d24725c commit 9d7b0ef

File tree

3 files changed

+54
-7
lines changed

3 files changed

+54
-7
lines changed

package.json

+5
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,11 @@
669669
"markdownDescription": "**Deprecated:** Specifies whether you should be prompted to update your version of `PackageManagement` if it's under 1.4.6.",
670670
"markdownDeprecationMessage": "**Deprecated:** This prompt has been removed as it's no longer strictly necessary to upgrade the `PackageManagement` module."
671671
},
672+
"powershell.suppressAdditionalExeNotFoundWarning": {
673+
"type": "boolean",
674+
"default": false,
675+
"markdownDescription": "Suppresses the warning message when any of `#powershell.powerShellAdditionalExePaths#` is not found."
676+
},
672677
"powershell.startAsLoginShell.osx": {
673678
"type": "boolean",
674679
"default": true,

src/platform.ts

+48-7
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
import * as os from "os";
55
import * as path from "path";
66
import * as process from "process";
7+
import vscode = require("vscode");
78
import { integer } from "vscode-languageserver-protocol";
89
import { ILogger } from "./logging";
9-
import { PowerShellAdditionalExePathSettings } from "./settings";
10+
import { changeSetting, getSettings, PowerShellAdditionalExePathSettings } from "./settings";
1011

1112
// This uses require so we can rewire it in unit tests!
1213
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-var-requires
@@ -149,8 +150,16 @@ export class PowerShellExeFinder {
149150
for (const additionalPwsh of this.enumerateAdditionalPowerShellInstallations()) {
150151
if (await additionalPwsh.exists()) {
151152
yield additionalPwsh;
152-
} else {
153-
void this.logger.writeAndShowWarning(`Additional PowerShell '${additionalPwsh.displayName}' not found at '${additionalPwsh.exePath}'!`);
153+
} else if (!additionalPwsh.suppressWarning) {
154+
const message = `Additional PowerShell '${additionalPwsh.displayName}' not found at '${additionalPwsh.exePath}'!`;
155+
this.logger.writeWarning(message);
156+
157+
if (!getSettings().suppressAdditionalExeNotFoundWarning) {
158+
const selection = await vscode.window.showWarningMessage(message, "Don't Show Again");
159+
if (selection !== undefined) {
160+
await changeSetting("suppressAdditionalExeNotFoundWarning", true, true, this.logger);
161+
}
162+
}
154163
}
155164
}
156165
}
@@ -223,9 +232,39 @@ export class PowerShellExeFinder {
223232
private *enumerateAdditionalPowerShellInstallations(): Iterable<IPossiblePowerShellExe> {
224233
for (const versionName in this.additionalPowerShellExes) {
225234
if (Object.prototype.hasOwnProperty.call(this.additionalPowerShellExes, versionName)) {
226-
const exePath = this.additionalPowerShellExes[versionName];
227-
if (exePath) {
228-
yield new PossiblePowerShellExe(exePath, versionName);
235+
let exePath = this.additionalPowerShellExes[versionName];
236+
if (!exePath) {
237+
continue;
238+
}
239+
240+
// Remove surrounding quotes from path (without regex)
241+
if (exePath.startsWith("'") && exePath.endsWith("'")
242+
|| exePath.startsWith("\"") && exePath.endsWith("\"")) {
243+
exePath = exePath.slice(1, -1);
244+
}
245+
246+
// Always search for what the user gave us first
247+
yield new PossiblePowerShellExe(exePath, versionName);
248+
249+
// Also search for `pwsh[.exe]` and `powershell[.exe]` if missing
250+
const args: [string, undefined, boolean, boolean]
251+
// Must be a tuple type and is suppressing the warning
252+
= [versionName, undefined, true, true];
253+
254+
// Handle Windows where '.exe' and 'powershell' are things
255+
if (this.platformDetails.operatingSystem === OperatingSystem.Windows) {
256+
if (!exePath.endsWith("pwsh.exe") && !exePath.endsWith("powershell.exe")) {
257+
if (exePath.endsWith("pwsh") || exePath.endsWith("powershell")) {
258+
// Add extension if that was missing
259+
yield new PossiblePowerShellExe(exePath + ".exe", ...args);
260+
}
261+
// Also add full exe names (this isn't an else just in case
262+
// the folder was named "pwsh" or "powershell")
263+
yield new PossiblePowerShellExe(path.join(exePath, "pwsh.exe"), ...args);
264+
yield new PossiblePowerShellExe(path.join(exePath, "powershell.exe"), ...args);
265+
}
266+
} else if (!exePath.endsWith("pwsh")) { // Always just 'pwsh' on non-Windows
267+
yield new PossiblePowerShellExe(path.join(exePath, "pwsh"), ...args);
229268
}
230269
}
231270
}
@@ -529,14 +568,16 @@ export function getWindowsSystemPowerShellPath(systemFolderName: string): string
529568

530569
interface IPossiblePowerShellExe extends IPowerShellExeDetails {
531570
exists(): Promise<boolean>;
571+
readonly suppressWarning: boolean;
532572
}
533573

534574
class PossiblePowerShellExe implements IPossiblePowerShellExe {
535575
constructor(
536576
public readonly exePath: string,
537577
public readonly displayName: string,
538578
private knownToExist?: boolean,
539-
public readonly supportsProperArguments = true) { }
579+
public readonly supportsProperArguments = true,
580+
public readonly suppressWarning = false) { }
540581

541582
public async exists(): Promise<boolean> {
542583
if (this.knownToExist === undefined) {

src/settings.ts

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export class Settings extends PartialSettings {
2323
// This setting is no longer used but is here to assist in cleaning up the users settings.
2424
powerShellExePath = "";
2525
promptToUpdatePowerShell = true;
26+
suppressAdditionalExeNotFoundWarning = false;
2627
startAsLoginShell = new StartAsLoginShellSettings();
2728
startAutomatically = true;
2829
enableProfileLoading = true;

0 commit comments

Comments
 (0)