Skip to content

Enable Searching for Pwsh in the "Program Files (Arm)" directory on Windows Arm64 #5225

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 87 additions & 77 deletions src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export interface IPlatformDetails {
operatingSystem: OperatingSystem;
isOS64Bit: boolean;
isProcess64Bit: boolean;
isArm64: boolean;
}

export interface IPowerShellExeDetails {
Expand All @@ -68,6 +69,7 @@ export function getPlatformDetails(): IPlatformDetails {
isOS64Bit:
isProcess64Bit || process.env.PROCESSOR_ARCHITEW6432 !== undefined,
isProcess64Bit,
isArm64: process.arch === "arm64",
};
}

Expand Down Expand Up @@ -562,93 +564,96 @@ export class PowerShellExeFinder {
}: { useAlternateBitness?: boolean; findPreview?: boolean } = {}): Promise<
IPossiblePowerShellExe | undefined
> {
Copy link
Preview

Copilot AI Jun 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a comment explaining the iteration over multiple ProgramFiles paths to clarify the search order and rationale.

Suggested change
> {
> {
// Iterate over possible `ProgramFiles` paths to locate PowerShell installations.
// This accounts for different system configurations, such as 32-bit and 64-bit installations,
// and ensures compatibility with alternate bitness settings if specified.

Copilot uses AI. Check for mistakes.

const programFilesPath = this.getProgramFilesPath({
for (const programFilesPath of this.getProgramFilesPath({
useAlternateBitness,
});
})) {

if (!programFilesPath) {
return undefined;
}
if (!programFilesPath) {
continue;
}

const powerShellInstallBaseDir = path.join(
programFilesPath,
"PowerShell",
);
const powerShellInstallBaseDir = path.join(
programFilesPath,
"PowerShell",
);

// Ensure the base directory exists
if (!(await utils.checkIfDirectoryExists(powerShellInstallBaseDir))) {
return undefined;
}
// Ensure the base directory exists
if (!(await utils.checkIfDirectoryExists(powerShellInstallBaseDir))) {
continue;
}

let highestSeenVersion = -1;
let pwshExePath: string | undefined;
for (const item of await utils.readDirectory(
powerShellInstallBaseDir,
)) {
let currentVersion = -1;
if (findPreview) {
// We are looking for something like "7-preview"

// Preview dirs all have dashes in them
const dashIndex: integer = item.indexOf("-");
if (dashIndex < 0) {
continue;
}
let highestSeenVersion = -1;
let pwshExePath: string | undefined;
for (const item of await utils.readDirectory(
powerShellInstallBaseDir,
)) {
let currentVersion = -1;
if (findPreview) {
// We are looking for something like "7-preview"

// Preview dirs all have dashes in them
const dashIndex: integer = item.indexOf("-");
if (dashIndex < 0) {
continue;
}

// Verify that the part before the dash is an integer
const intPart: string = item.substring(0, dashIndex);
if (!PowerShellExeFinder.IntRegex.test(intPart)) {
continue;
// Verify that the part before the dash is an integer
const intPart: string = item.substring(0, dashIndex);
if (!PowerShellExeFinder.IntRegex.test(intPart)) {
continue;
}

// Verify that the part after the dash is "preview"
if (item.substring(dashIndex + 1) !== "preview") {
continue;
}

currentVersion = parseInt(intPart, 10);
} else {
// Search for a directory like "6" or "7"
if (!PowerShellExeFinder.IntRegex.test(item)) {
continue;
}

currentVersion = parseInt(item, 10);
}

// Verify that the part after the dash is "preview"
if (item.substring(dashIndex + 1) !== "preview") {
// Ensure we haven't already seen a higher version
if (currentVersion <= highestSeenVersion) {
continue;
}

currentVersion = parseInt(intPart, 10);
} else {
// Search for a directory like "6" or "7"
if (!PowerShellExeFinder.IntRegex.test(item)) {
// Now look for the file
const exePath = path.join(
powerShellInstallBaseDir,
item,
"pwsh.exe",
);
if (!(await utils.checkIfFileExists(exePath))) {
continue;
}

currentVersion = parseInt(item, 10);
pwshExePath = exePath;
highestSeenVersion = currentVersion;
}

// Ensure we haven't already seen a higher version
if (currentVersion <= highestSeenVersion) {
if (!pwshExePath) {
continue;
}

// Now look for the file
const exePath = path.join(
powerShellInstallBaseDir,
item,
"pwsh.exe",
);
if (!(await utils.checkIfFileExists(exePath))) {
continue;
}
const bitness: string = programFilesPath.includes("x86")
? "(x86)"
: "(x64)";

pwshExePath = exePath;
highestSeenVersion = currentVersion;
}
const preview: string = findPreview ? " Preview" : "";

if (!pwshExePath) {
return undefined;
return new PossiblePowerShellExe(
pwshExePath,
`PowerShell${preview} ${bitness}`,
);
}

const bitness: string = programFilesPath.includes("x86")
? "(x86)"
: "(x64)";

const preview: string = findPreview ? " Preview" : "";

return new PossiblePowerShellExe(
pwshExePath,
`PowerShell${preview} ${bitness}`,
);
return undefined;
}

private findWinPS({
Expand Down Expand Up @@ -707,24 +712,29 @@ export class PowerShellExeFinder {

private getProgramFilesPath({
useAlternateBitness = false,
}: { useAlternateBitness?: boolean } = {}): string | undefined {
}: { useAlternateBitness?: boolean } = {}): (string | undefined)[] {
const result: (string | undefined)[] = [];

if (!useAlternateBitness) {
// Just use the native system bitness
return process.env.ProgramFiles;
}
result.push(process.env.ProgramFiles);

// We might be a 64-bit process looking for 32-bit program files
if (this.platformDetails.isProcess64Bit) {
return process.env["ProgramFiles(x86)"];
}
// We might be a Arm64 process looking for Arm program files
if (this.platformDetails.isArm64) {
result.push(process.env["ProgramFiles(Arm)"]);
}
} else {
// We might be a 64-bit process looking for 32-bit program files
if (this.platformDetails.isProcess64Bit) {
result.push(process.env["ProgramFiles(x86)"]);
}

// We might be a 32-bit process looking for 64-bit program files
if (this.platformDetails.isOS64Bit) {
return process.env.ProgramW6432;
// We might be a 32-bit process looking for 64-bit program files
if (this.platformDetails.isOS64Bit) {
result.push(process.env.ProgramW6432);
}
}

// We're a 32-bit process on 32-bit Windows, there is no other Program Files dir
return undefined;
return result;
}

private getSystem32Path({
Expand Down
Loading