fswin32
Version:
The ultimate Node.js module for detailed Windows file system access.
86 lines (75 loc) • 3.15 kB
JavaScript
// src/drives.js
import { promises as fs } from 'fs';
import { executePowerShellCommand, formatBytes } from './utils.js';
/**
* Gets a list of accessible Windows drives.
* It first checks all A-Z drive letters directly using fs.access for speed.
* PowerShell is used only as a last resort fallback if no drives are found.
* @returns {Promise<Array<string>>} An array of accessible drive letters.
*/
export const getAccessibleDrives = async () => {
let drives = [];
const driveLetters = [];
// Primary, faster method: Check A-Z drives with fs.access
for (let i = 65; i <= 90; i++) {
driveLetters.push(String.fromCharCode(i));
}
// Use Promise.all to check all drives concurrently for max speed
const driveAccessChecks = driveLetters.map(async (letter) => {
const drivePath = `${letter}:\\`;
try {
await fs.access(drivePath);
return letter;
} catch (error) {
return null; // Drive is not accessible, return null
}
});
const results = await Promise.all(driveAccessChecks);
drives = results.filter(Boolean); // Filter out null values
// Fallback only if no drives are found through the fast method
if (drives.length === 0) {
const stdout = await executePowerShellCommand('Get-WmiObject -Class Win32_LogicalDisk | Select-Object DeviceID');
if (stdout) {
stdout.split('\n').forEach(line => {
const match = line.match(/^([A-Z]):/);
if (match) drives.push(match[1]);
});
}
}
return [...new Set(drives)];
};
/**
* Gets detailed information about a specific Windows drive using PowerShell.
* @param {string} driveLetter The letter of the drive (e.g., 'C').
* @returns {Promise<Object|null>} An object with drive details or null on failure.
*/
export const getDriveDetails = async (driveLetter) => {
const command = `Get-WmiObject -Class Win32_LogicalDisk | Where-Object {$_.DeviceID -eq '${driveLetter}:'} | Select-Object Size, FreeSpace, VolumeName | Format-List`;
const stdout = await executePowerShellCommand(command);
if (stdout) {
const lines = stdout.split('\n').filter(line => line.trim());
const details = {};
lines.forEach(line => {
const [key, value] = line.split(':').map(s => s.trim());
if (key && value) {
details[key] = value;
}
});
if (details.Size && details.FreeSpace) {
const totalSpaceBytes = parseInt(details.Size, 10);
const freeSpaceBytes = parseInt(details.FreeSpace, 10);
const usedSpaceBytes = totalSpaceBytes - freeSpaceBytes;
return {
drive: driveLetter,
volumeName: details.VolumeName || 'N/A',
totalSpace: formatBytes(totalSpaceBytes),
freeSpace: formatBytes(freeSpaceBytes),
usedSpace: formatBytes(usedSpaceBytes),
totalSpaceBytes,
freeSpaceBytes,
usedSpaceBytes,
};
}
}
return null;
};