Fix reading images from network drives on windows when the tmp dir has spaces

Changelog-entry: (Windows): Fix reading images from network drives when the tmp dir has spaces
Change-type: patch
This commit is contained in:
Alexis Svinartchouk 2019-04-16 13:44:25 +02:00
parent 9da9e73f7a
commit 11def54adb

View File

@ -79,36 +79,7 @@ const tmpFileDisposer = () => {
const readFileAsync = promisify(fs.readFile)
/**
* @summary Promisified child_process.execFile
* @function
*
* @param {String} file - command
* @param {String[]} args - arguments
* @param {Object} options - child_process.execFile options
*
* @returns {Promise<Object>} - { stdout, stderr }
*
* @example
* execFileAsync('ls', [ '.' ])
* .then(console.log);
*/
const execFileAsync = async (file, args, options) => {
return new Promise((resolve, reject) => {
cp.execFile(
file,
args,
options,
(error, stdout, stderr) => {
if (error) {
reject(error)
} else {
resolve({ stdout, stderr })
}
}
)
})
}
const execAsync = promisify(cp.exec)
/**
* @summary Returns wmic's output for network drives
@ -121,27 +92,27 @@ const execFileAsync = async (file, args, options) => {
*/
exports.getWmicNetworkDrivesOutput = async () => {
// Exported for tests.
// Windows's wmic outputs ucs2 encoded data.
// When trying to read its stdout from node's execFile, it is always transformed (even if you pass { encoding: 'buffer' })
// Information is lost and accented characters become unreadable (with no way to guess what they were).
// Because of this, we use the wmic's "/output:" switch that redirects the output to a file.
// For some reason wmic doesn't like dashes in filenames, that's why we change the tmp file prefix in tmpFileAsync above.
// When trying to read wmic's stdout directly from node, it is encoded with the current
// console codepage (depending on the computer).
// Decoding this would require getting this codepage somehow and using iconv as node
// doesn't know how to read cp850 directly for example.
// We could also use wmic's "/output:" switch but it doesn't work when the filename
// contains a space and the os temp dir may contain spaces ("D:\Windows Temp Files" for example).
// So we just redirect to a file and read it afterwards as we know it will be ucs2 encoded.
return Bluebird.using(tmpFileDisposer(), async ({ path }) => {
await execFileAsync(
const command = [
Path.join(process.env.SystemRoot, 'System32', 'Wbem', 'wmic'),
[
`/output:${path}`,
'path',
'Win32_LogicalDisk',
'Where',
'DriveType="4"',
'get',
'DeviceID,ProviderName'
],
{ windowsHide: true, windowsVerbatimArguments: true }
)
const data = await readFileAsync(path, 'ucs2')
return data
'DeviceID,ProviderName',
'>',
`"${path}"`
]
await execAsync(command.join(' '), { windowsHide: true })
return readFileAsync(path, 'ucs2')
})
}