|
4 | 4 | import * as os from "os";
|
5 | 5 | import * as path from "path";
|
6 | 6 | import * as process from "process";
|
| 7 | +import vscode = require("vscode"); |
7 | 8 | import { integer } from "vscode-languageserver-protocol";
|
8 | 9 | import { ILogger } from "./logging";
|
9 |
| -import { PowerShellAdditionalExePathSettings } from "./settings"; |
| 10 | +import { changeSetting, getSettings, PowerShellAdditionalExePathSettings } from "./settings"; |
10 | 11 |
|
11 | 12 | // This uses require so we can rewire it in unit tests!
|
12 | 13 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-var-requires
|
@@ -149,8 +150,12 @@ export class PowerShellExeFinder {
|
149 | 150 | for (const additionalPwsh of this.enumerateAdditionalPowerShellInstallations()) {
|
150 | 151 | if (await additionalPwsh.exists()) {
|
151 | 152 | yield additionalPwsh;
|
152 |
| - } else { |
153 |
| - void this.logger.writeAndShowWarning(`Additional PowerShell '${additionalPwsh.displayName}' not found at '${additionalPwsh.exePath}'!`); |
| 153 | + } else if (!additionalPwsh.suppressWarning |
| 154 | + && !getSettings().suppressAdditionalExeNotFoundWarning) { |
| 155 | + const selection = await vscode.window.showWarningMessage(`Additional PowerShell '${additionalPwsh.displayName}' not found at '${additionalPwsh.exePath}'!`, "Don't Show Again"); |
| 156 | + if (selection !== undefined) { |
| 157 | + await changeSetting("suppressAdditionalExeNotFoundWarning", true, true, this.logger); |
| 158 | + } |
154 | 159 | }
|
155 | 160 | }
|
156 | 161 | }
|
@@ -223,9 +228,39 @@ export class PowerShellExeFinder {
|
223 | 228 | private *enumerateAdditionalPowerShellInstallations(): Iterable<IPossiblePowerShellExe> {
|
224 | 229 | for (const versionName in this.additionalPowerShellExes) {
|
225 | 230 | if (Object.prototype.hasOwnProperty.call(this.additionalPowerShellExes, versionName)) {
|
226 |
| - const exePath = this.additionalPowerShellExes[versionName]; |
227 |
| - if (exePath) { |
228 |
| - yield new PossiblePowerShellExe(exePath, versionName); |
| 231 | + let exePath = this.additionalPowerShellExes[versionName]; |
| 232 | + if (!exePath) { |
| 233 | + continue; |
| 234 | + } |
| 235 | + |
| 236 | + // Remove surrounding quotes from path (without regex) |
| 237 | + if (exePath.startsWith("'") && exePath.endsWith("'") |
| 238 | + || exePath.startsWith("\"") && exePath.endsWith("\"")) { |
| 239 | + exePath = exePath.slice(1, -1); |
| 240 | + } |
| 241 | + |
| 242 | + // Always search for what the user gave us first |
| 243 | + yield new PossiblePowerShellExe(exePath, versionName); |
| 244 | + |
| 245 | + // Also search for `pwsh[.exe]` and `powershell[.exe]` if missing |
| 246 | + const args: [string, undefined, boolean, boolean] |
| 247 | + // Must be a tuple type and is suppressing the warning |
| 248 | + = [versionName, undefined, true, true]; |
| 249 | + |
| 250 | + // Handle Windows where '.exe' and 'powershell' are things |
| 251 | + if (this.platformDetails.operatingSystem === OperatingSystem.Windows) { |
| 252 | + if (!exePath.endsWith("pwsh.exe") && !exePath.endsWith("powershell.exe")) { |
| 253 | + if (exePath.endsWith("pwsh") || exePath.endsWith("powershell")) { |
| 254 | + // Add extension if that was missing |
| 255 | + yield new PossiblePowerShellExe(exePath + ".exe", ...args); |
| 256 | + } |
| 257 | + // Also add full exe names (this isn't an else just in case |
| 258 | + // the folder was named "pwsh" or "powershell") |
| 259 | + yield new PossiblePowerShellExe(path.join(exePath, "pwsh.exe"), ...args); |
| 260 | + yield new PossiblePowerShellExe(path.join(exePath, "powershell.exe"), ...args); |
| 261 | + } |
| 262 | + } else if (!exePath.endsWith("pwsh")) { // Always just 'pwsh' on non-Windows |
| 263 | + yield new PossiblePowerShellExe(path.join(exePath, "pwsh"), ...args); |
229 | 264 | }
|
230 | 265 | }
|
231 | 266 | }
|
@@ -529,14 +564,16 @@ export function getWindowsSystemPowerShellPath(systemFolderName: string): string
|
529 | 564 |
|
530 | 565 | interface IPossiblePowerShellExe extends IPowerShellExeDetails {
|
531 | 566 | exists(): Promise<boolean>;
|
| 567 | + readonly suppressWarning: boolean; |
532 | 568 | }
|
533 | 569 |
|
534 | 570 | class PossiblePowerShellExe implements IPossiblePowerShellExe {
|
535 | 571 | constructor(
|
536 | 572 | public readonly exePath: string,
|
537 | 573 | public readonly displayName: string,
|
538 | 574 | private knownToExist?: boolean,
|
539 |
| - public readonly supportsProperArguments = true) { } |
| 575 | + public readonly supportsProperArguments = true, |
| 576 | + public readonly suppressWarning = false) { } |
540 | 577 |
|
541 | 578 | public async exists(): Promise<boolean> {
|
542 | 579 | if (this.knownToExist === undefined) {
|
|
0 commit comments