You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
child_process execFile / spawn throw non-descript exception on windows if exe requires elevation #9464
let cp = require('child_process');
let util = require('util');
try {
cp.execFileSync('SomeTool.exe')
} catch (err) {
console.log('err', util.inspect(err));
}
outputs
err { Error: spawnSync SomeTool.exe UNKNOWN
at exports._errnoException (util.js:1026:11)
at spawnSync (child_process.js:461:20)
at Object.execFileSync (child_process.js:498:13)
at repl:2:4
at sigintHandlersWrap (vm.js:22:35)
at sigintHandlersWrap (vm.js:96:12)
at ContextifyScript.Script.runInThisContext (vm.js:21:12)
at REPLServer.defaultEval (repl.js:313:29)
at bound (domain.js:280:14)
at REPLServer.runBound [as eval] (domain.js:293:12)
code: 'UNKNOWN',
errno: 'UNKNOWN',
...
}
spawn generates the same error.
Obviously it would be better if this error was returned through the callback but I would also love to have a proper error code to react to the situation.
Not sure how execFile and spawn are implemented but it should be possible to report a proper errorcode as CreateProcess generates errorcode 740 if elevation is required.
It doesn't work like this. As I said: SomeTool.exe requires elevation, which means if you start it in cmd.exe or powershell it displays a UAC dialog and if the user accepts it the application is run in a separate administrator shell. The orignal shell doesn't receive an exit code.
However, running execFile/spawn from node does not display an UAC dialog to begin with so SomeTool.exe isn't started at all. It can't be - unless node exploits a security bug in Windows to circumvent security measures. Whatever api node/libuv is using to spawn a process (I assume CreateProcess because ShellExecute would work and display a UAC dialog) fails immediately with an error code that says the user doesn't have the permission to run that exe and node doesn't report that error code back to the application.
I just updated to node 6.9.1 to repeat the test. I also realized that using execFileSync might hide an aspect of the problem:
let cp = require('child_process');
let util = require('util');
try {
cp.execFile('SomeTool.exe', (err, out) => {
if (err) {
console.log('err', err);
}
});
} catch (ex) {
console.log('exception', ex);
}
reports:
exception { Error: spawn UNKNOWN
at exports._errnoException (util.js:1026:11)
at ChildProcess.spawn (internal/child_process.js:313:11)
at exports.spawn (child_process.js:380:9)
...
As you see, the error is reported synchronously as an exception, not as an error through the callback.
Activity
silverwind commentedon Nov 5, 2016
Does
SomeTool.exeactually exit with this error level? Try in PowerShell:TanninOne commentedon Nov 6, 2016
It doesn't work like this. As I said: SomeTool.exe requires elevation, which means if you start it in cmd.exe or powershell it displays a UAC dialog and if the user accepts it the application is run in a separate administrator shell. The orignal shell doesn't receive an exit code.
However, running execFile/spawn from node does not display an UAC dialog to begin with so SomeTool.exe isn't started at all. It can't be - unless node exploits a security bug in Windows to circumvent security measures. Whatever api node/libuv is using to spawn a process (I assume CreateProcess because ShellExecute would work and display a UAC dialog) fails immediately with an error code that says the user doesn't have the permission to run that exe and node doesn't report that error code back to the application.
I just updated to node 6.9.1 to repeat the test. I also realized that using execFileSync might hide an aspect of the problem:
reports:
As you see, the error is reported synchronously as an exception, not as an error through the callback.
silverwind commentedon Nov 6, 2016
FYI, It's using CreateProcess.
richardlau commentedon Nov 30, 2016
UNKNOWNis becauseERROR_ELEVATION_REQUIRED(740) is not translated in uv_translate_sys_error(). I'll submit a fix upstream.win: map ERROR_ELEVATION_REQUIRED to UV_EACCES
win: map ERROR_ELEVATION_REQUIRED to UV_EACCES
win: map ERROR_ELEVATION_REQUIRED to UV_EACCES
win: map ERROR_ELEVATION_REQUIRED to UV_EACCES
richardlau commentedon Nov 30, 2016
libuv/libuv#1154
win: map ERROR_ELEVATION_REQUIRED to UV_EACCES
win: map ERROR_ELEVATION_REQUIRED to UV_EACCES
win: map ERROR_ELEVATION_REQUIRED to UV_EACCES
5 remaining items
richardlau commentedon Dec 16, 2016
Should this remain open until Node.js is updated to a version of libuv containing the fix?
silverwind commentedon Dec 16, 2016
Yes, I'd say so.
deps: upgrade libuv to 1.10.2
win: map ERROR_ELEVATION_REQUIRED to UV_EACCES
deps: upgrade libuv to 1.10.2
deps: upgrade libuv to 1.10.2
deps: upgrade libuv to 1.10.2
deps: upgrade libuv to 1.10.2
deps: upgrade libuv to 1.10.2
deps: upgrade libuv to 1.10.2
deps: upgrade libuv to 1.10.2