UNPKG

detect-shell

Version:
308 lines 14.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var g = generator.apply(thisArg, _arguments || []), i, q = []; return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } }; var __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.enumeratePowerShellInstallations = void 0; const pfs = __importStar(require("./pfs")); const os_1 = __importDefault(require("os")); const path_1 = __importDefault(require("path")); const process_1 = require("process"); const WindowsPowerShell64BitLabel = 'Windows PowerShell'; const WindowsPowerShell32BitLabel = 'Windows PowerShell (x86)'; // This is required, since parseInt("7-preview") will return 7. const IntRegex = /^\d+$/; const PwshMsixRegex = /^Microsoft.PowerShell_.*/; const PwshPreviewMsixRegex = /^Microsoft.PowerShellPreview_.*/; // The platform details descriptor for the platform we're on const isProcess64Bit = process.arch === 'x64'; const isOS64Bit = isProcess64Bit || os_1.default.arch() === 'x64'; class PossiblePowerShellExe { constructor(exePath, displayName, knownToExist) { this.exePath = exePath; this.displayName = displayName; this.knownToExist = knownToExist; } exists() { return __awaiter(this, void 0, void 0, function* () { if (this.knownToExist === undefined) { this.knownToExist = yield pfs.fileExists(this.exePath); } return this.knownToExist; }); } } function getProgramFilesPath({ useAlternateBitness = false } = {}) { if (!useAlternateBitness) { // Just use the native system bitness return process_1.env.ProgramFiles || null; } // We might be a 64-bit process looking for 32-bit program files if (isProcess64Bit) { return process_1.env['ProgramFiles(x86)'] || null; } // We might be a 32-bit process looking for 64-bit program files if (isOS64Bit) { return process_1.env.ProgramW6432 || null; } // We're a 32-bit process on 32-bit Windows, there is no other Program Files dir return null; } function getSystem32Path({ useAlternateBitness = false } = {}) { const windir = process_1.env.windir; if (!useAlternateBitness) { // Just use the native system bitness return path_1.default.join(windir, 'System32'); } // We might be a 64-bit process looking for 32-bit system32 if (isProcess64Bit) { return path_1.default.join(windir, 'SysWOW64'); } // We might be a 32-bit process looking for 64-bit system32 if (isOS64Bit) { return path_1.default.join(windir, 'Sysnative'); } // We're on a 32-bit Windows, so no alternate bitness return path_1.default.join(windir, 'System32'); } function findPSCoreWindowsInstallation({ useAlternateBitness = false, findPreview = false } = {}) { return __awaiter(this, void 0, void 0, function* () { const programFilesPath = getProgramFilesPath({ useAlternateBitness }); if (!programFilesPath) { return null; } const powerShellInstallBaseDir = path_1.default.join(programFilesPath, 'PowerShell'); // Ensure the base directory exists if (!(yield pfs.dirExists(powerShellInstallBaseDir))) { return null; } let highestSeenVersion = -1; let pwshExePath = null; for (const item of yield pfs.readdir(powerShellInstallBaseDir)) { let currentVersion = -1; if (findPreview) { // We are looking for something like "7-preview" // Preview dirs all have dashes in them const dashIndex = item.indexOf('-'); if (dashIndex < 0) { continue; } // Verify that the part before the dash is an integer // and that the part after the dash is "preview" const intPart = item.substring(0, dashIndex); if (!IntRegex.test(intPart) || item.substring(dashIndex + 1) !== 'preview') { continue; } currentVersion = parseInt(intPart, 10); } else { // Search for a directory like "6" or "7" if (!IntRegex.test(item)) { continue; } currentVersion = parseInt(item, 10); } // Ensure we haven't already seen a higher version if (currentVersion <= highestSeenVersion) { continue; } // Now look for the file const exePath = path_1.default.join(powerShellInstallBaseDir, item, 'pwsh.exe'); if (!(yield pfs.fileExists(exePath))) { continue; } pwshExePath = exePath; highestSeenVersion = currentVersion; } if (!pwshExePath) { return null; } const bitness = programFilesPath.includes('x86') ? ' (x86)' : ''; const preview = findPreview ? ' Preview' : ''; return new PossiblePowerShellExe(pwshExePath, `PowerShell${preview}${bitness}`, true); }); } function findPSCoreMsix({ findPreview } = {}) { return __awaiter(this, void 0, void 0, function* () { // We can't proceed if there's no LOCALAPPDATA path if (!process_1.env.LOCALAPPDATA) { return null; } // Find the base directory for MSIX application exe shortcuts const msixAppDir = path_1.default.join(process_1.env.LOCALAPPDATA, 'Microsoft', 'WindowsApps'); if (!(yield pfs.dirExists(msixAppDir))) { return null; } // Define whether we're looking for the preview or the stable const { pwshMsixDirRegex, pwshMsixName } = findPreview ? { pwshMsixDirRegex: PwshPreviewMsixRegex, pwshMsixName: 'PowerShell Preview (Store)' } : { pwshMsixDirRegex: PwshMsixRegex, pwshMsixName: 'PowerShell (Store)' }; // We should find only one such application, so return on the first one for (const subdir of yield pfs.readdir(msixAppDir)) { if (pwshMsixDirRegex.test(subdir)) { const pwshMsixPath = path_1.default.join(msixAppDir, subdir, 'pwsh.exe'); return new PossiblePowerShellExe(pwshMsixPath, pwshMsixName); } } // If we find nothing, return null return null; }); } function findPSCoreDotnetGlobalTool() { const dotnetGlobalToolExePath = path_1.default.join(os_1.default.homedir(), '.dotnet', 'tools', 'pwsh.exe'); return new PossiblePowerShellExe(dotnetGlobalToolExePath, '.NET Core PowerShell Global Tool'); } function findWinPS({ useAlternateBitness = false } = {}) { // x86 and ARM only have one WinPS on them if (!isOS64Bit && useAlternateBitness) { return null; } const systemFolderPath = getSystem32Path({ useAlternateBitness }); const winPSPath = path_1.default.join(systemFolderPath, 'WindowsPowerShell', 'v1.0', 'powershell.exe'); let displayName; if (isProcess64Bit) { displayName = useAlternateBitness ? WindowsPowerShell32BitLabel : WindowsPowerShell64BitLabel; } else if (isOS64Bit) { displayName = useAlternateBitness ? WindowsPowerShell64BitLabel : WindowsPowerShell32BitLabel; } else { // NOTE: ARM Windows devices also have Windows PowerShell x86 on them. There is no // "ARM Windows PowerShell". displayName = WindowsPowerShell32BitLabel; } return new PossiblePowerShellExe(winPSPath, displayName, true); } /** * Iterates through all the possible well-known PowerShell installations on a machine. * Returned values may not exist, but come with an .exists property * which will check whether the executable exists. */ function enumerateDefaultPowerShellInstallations() { return __asyncGenerator(this, arguments, function* enumerateDefaultPowerShellInstallations_1() { // Find PSCore stable first let pwshExe = yield __await(findPSCoreWindowsInstallation()); if (pwshExe) { yield yield __await(pwshExe); } // Windows may have a 32-bit pwsh.exe pwshExe = yield __await(findPSCoreWindowsInstallation({ useAlternateBitness: true })); if (pwshExe) { yield yield __await(pwshExe); } // Also look for the MSIX/UWP installation pwshExe = yield __await(findPSCoreMsix()); if (pwshExe) { yield yield __await(pwshExe); } // Look for the .NET global tool // Some older versions of PowerShell have a bug in this where startup will fail, // but this is fixed in newer versions pwshExe = findPSCoreDotnetGlobalTool(); if (pwshExe) { yield yield __await(pwshExe); } // Look for PSCore preview pwshExe = yield __await(findPSCoreWindowsInstallation({ findPreview: true })); if (pwshExe) { yield yield __await(pwshExe); } // Find a preview MSIX pwshExe = yield __await(findPSCoreMsix({ findPreview: true })); if (pwshExe) { yield yield __await(pwshExe); } // Look for pwsh-preview with the opposite bitness pwshExe = yield __await(findPSCoreWindowsInstallation({ useAlternateBitness: true, findPreview: true })); if (pwshExe) { yield yield __await(pwshExe); } // Finally, get Windows PowerShell // Get the natural Windows PowerShell for the process bitness pwshExe = findWinPS(); if (pwshExe) { yield yield __await(pwshExe); } // Get the alternate bitness Windows PowerShell pwshExe = findWinPS({ useAlternateBitness: true }); if (pwshExe) { yield yield __await(pwshExe); } }); } /** * Iterates through PowerShell installations on the machine according * to configuration passed in through the constructor. * PowerShell items returned by this object are verified * to exist on the filesystem. */ function enumeratePowerShellInstallations() { return __asyncGenerator(this, arguments, function* enumeratePowerShellInstallations_1() { var e_1, _a; try { // Get the default PowerShell installations first for (var _b = __asyncValues(enumerateDefaultPowerShellInstallations()), _c; _c = yield __await(_b.next()), !_c.done;) { const defaultPwsh = _c.value; if (yield __await(defaultPwsh.exists())) { yield yield __await(defaultPwsh); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) yield __await(_a.call(_b)); } finally { if (e_1) throw e_1.error; } } }); } exports.enumeratePowerShellInstallations = enumeratePowerShellInstallations; //# sourceMappingURL=powershell.js.map