Skip to content
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

Fix PowerShell MSIX (Store) detection #3202

Merged
merged 1 commit into from
Feb 25, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 20 additions & 3 deletions src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ export class PowerShellExeFinder {
// Find the base directory for MSIX application exe shortcuts
const msixAppDir = path.join(process.env.LOCALAPPDATA, "Microsoft", "WindowsApps");

if (!fs.existsSync(msixAppDir)) {
Copy link
Member

Choose a reason for hiding this comment

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

Good call to remove this anyway:

fs.existsSync() will be deprecated.

if (!fileExistsSync(msixAppDir)) {
return null;
}

Expand Down Expand Up @@ -310,7 +310,13 @@ export class PowerShellExeFinder {
const powerShellInstallBaseDir = path.join(programFilesPath, "PowerShell");

// Ensure the base directory exists
if (!(fs.existsSync(powerShellInstallBaseDir) && fs.lstatSync(powerShellInstallBaseDir).isDirectory())) {
try {
const powerShellInstallBaseDirLStat = fs.lstatSync(powerShellInstallBaseDir);
if (!powerShellInstallBaseDirLStat.isDirectory())
{
return null;
}
} catch {
return null;
}

Expand Down Expand Up @@ -469,6 +475,17 @@ export function getWindowsSystemPowerShellPath(systemFolderName: string) {
"powershell.exe");
}

function fileExistsSync(filePath: string): boolean {
Copy link
Member

Choose a reason for hiding this comment

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

The node docs aren't wrong about this kinda being an anti-pattern.

fs.exists() is an anachronism and exists only for historical reasons. There should almost never be a reason to use it in your own code.

In particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to fs.exists() and fs.open(). Just open the file and handle the error when it's not there.

fs.exists() will be deprecated.

We're essentially making our own fs.existsSync and I question if we need it. As the code is written right now, this does seem to be the best option, but I'd want to review why we're checking if a file exists, then checking if a folder exists, etc.

try {
// This will throw if the path does not exist,
// and otherwise returns a value that we don't care about
fs.lstatSync(filePath);
Copy link
Member

Choose a reason for hiding this comment

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

This probably ought to just be fs.statSync since we don't care about the information, but we may care that the target file exists. I don't really care though, as the code as written is (presumably) tested, and it's not really our problem if the symlink exists but its target does not.

return true;
} catch {
return false;
}
}

interface IPossiblePowerShellExe extends IPowerShellExeDetails {
exists(): boolean;
}
Expand All @@ -491,7 +508,7 @@ class PossiblePowerShellExe implements IPossiblePowerShellExe {

public exists(): boolean {
if (this.knownToExist === undefined) {
this.knownToExist = fs.existsSync(this.exePath);
this.knownToExist = fileExistsSync(this.exePath);
}
return this.knownToExist;
}
Expand Down