Skip to content
This repository has been archived by the owner on Jun 22, 2021. It is now read-only.

Consider .bat and .cmd files when spawning a process on Windows? #170

Open
gaborcsardi opened this issue Sep 22, 2020 · 8 comments
Open

Comments

@gaborcsardi
Copy link

gaborcsardi commented Sep 22, 2020

For filename libuv currently considers starting filename, filename.com and filename.exe when spawning a process on Windows.

Is there a reason why .bat and .cmd files are left out? FWIW you can run them in a cmd.exe without specifying the extension, and cmd.exe looks for them in the .exe, .bat, .cmd order.

@bnoordhuis
Copy link
Member

It's exactly because of the fact that it's a cmd.exe feature, not a CreateProcess feature. You can emulate it by prepending the command with cmd.exe /c.

As an aside: the list of extensions isn't hard-coded, it's set by the PATHEXT environment variable.

@gaborcsardi
Copy link
Author

gaborcsardi commented Sep 22, 2020

Maybe I am missing something, but:

Is there a reason why libuv does not use PATHEXT?

Anyway, following the docs is a good enough reason not to allow .bat and .cmd files.

@bnoordhuis
Copy link
Member

That CreateProcess() knows how to spawn batch files is news to me... do you know if that is a recent development?

@gaborcsardi
Copy link
Author

gaborcsardi commented Sep 22, 2020

I don't think it is. I just tried it on Windows Vista. (Not with libuv, though, but a "manual" CreateProcessW() call.)

But here it is with node on Windows 8.1:

C:\Users\Gabor>type test.js
const { spawn } = require('child_process');
const bat = spawn('ls.bat');

bat.stdout.on('data', (data) => {
  console.log(data.toString());
});

bat.stderr.on('data', (data) => {
  console.error(data.toString());
});

bat.on('exit', (code) => {
  console.log(`Child exited with code ${code}`);
});

C:\Users\Gabor>type ls.bat
echo foobar2

C:\Users\Gabor>node test.js

C:\Users\Gabor>echo foobar2

Child exited with code 0
foobar2


C:\Users\Gabor>

Am I missing something? Is this some special case and it does not work in general? The internet is full with docs that say that this does not work...

@bnoordhuis
Copy link
Member

@libuv/windows Is the above known to you?

@vtjnash
Copy link
Member

vtjnash commented Sep 22, 2020

Yes, it's documented here https://github.com/libuv/libuv/blob/2a1b880f5439e074ef4d5c556f626b1044fb6781/src/win/process.c#L304-L308

IIRC, nodejs does some hack-y pattern matching, and isn't calling uv_spawn directly in the above test (I say hacky, because I recall seeing bug reports that it mangles the command line arguments incorrectly)

@gaborcsardi
Copy link
Author

@vtjnash well, that says kind of the opposite of what I find. I.e. I found that CreateProcess can start .bat and .cmd files.

@vtjnash
Copy link
Member

vtjnash commented Sep 23, 2020

It's also documented here that only .exe and .com should be specified: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw, so you may want to ask Microsoft to fix their documentation first, since they also say it should not be assumed to work this way:

To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the following arguments: /c plus the name of the batch file.

I did some quick local testing too, and seems like it works for me also on Windows 10 and Windows XP however. Though nodejs is also very clear that it should not https://nodejs.org/api/child_process.html#child_process_spawning_bat_and_cmd_files_on_windows

(Aside, note that for for reliability, your usage example of nodejs above must set the windowsVerbatimArguments option and implement argument quoting yourself.)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants