Closed ChrisDenton closed 1 year ago
Finding cmd.exe
can be done by inspecting the ComSpec
Environment variable.
We don't have any existing machinery to deal with the Windows Registry in the Rust standard library at the moment do we? So to access it we would need to import more libraries or use a different program such as REG
. Using the registry APIs would be the cleanest approach though.
Finding cmd.exe can be done by inspecting the ComSpec Environment variable.
True. Though we may need a fallback if that's not available for some reason. Also we'd need to consider if using the environment for this could be a security risk in some scenarios. Possibly not, but it's worth considering before implementing.
We don't have any existing machinery to deal with the Windows Registry in the Rust standard library at the moment do we? So to access it we would need to import more libraries or use a different program such as REG. Using the registry APIs would be the cleanest approach though.
Yeah, we don't currently use any registry APIs so those would need to be added. And there would also be a fair amount of effort to ensure the logic for resolving the script's application is all implemented correctly.
Another question is if running scripts does belong in the standard library, given the added complexity involved, or whether it's enough for a third party crate to implement it. There is at least some demand for it though (which is why I made this issue).
I would like to see implementations for scripts and registry handling in external crates first. When it's something we already have started doing, like running executables, then adding more ways to talk about that is one thing, since it's merely extending what we do. But I don't think we should add a lot of API surface for a particular OS and its nonstandard interfaces if we don't have some experimentation first to see what a good Rust interface would look like. Indeed, such things may be particular to the OS version as well.
I don't think the cost of adding code to talk to the registry is really the decider here. It's a few functions, and they're relatively straightforward to use, and fairly portable across versions.
That said, I don't think we should do this — it's not really std's place to implement this kind of support IMO. We also don't support running scripts in all cases on Unix, for example in the case of shebang-less scripts; see #101511, and in particular this comment https://github.com/rust-lang/rust/issues/101511#issuecomment-1239531706, where we decided not to fall back to trying sh
, which seems just about like the Unix equivalent of this.
Just to be clear, this isn't proposing any new public API per se, just that the existing API works with non-.exe
(aka non-PE) files. However, this would complicate the implementation. And that complexity comes not from the extra OS APIs (although that does add some) but from the logic needed to do this all correctly. There is a function, ShellExecuteExW
, that can do a lot of the work for us but this comes with major limitations (e.g. you can't redirect stdio).
The reason I made this issue is this is a common request. People are often surprised that this doesn't work already. Even Windows users may expect it to work (depending on where they're coming from). So I wanted to walkthrough what it would mean for us to support it.
Oh okay! I guess I didn't quite parse what you meant. So those are just internal changes, and people want us to be able to run scripts.
Hmm.
Yeah, I'm kinda with Thom: I'm still inclined to say "nah". I feel like Command::spawn
morally should be "please chuck this directly into the program loader in the way that makes this an independent program-object on this OS". If this happens to run a script because that's how programs get loaded on this particular OS (as with shebangs), that's fine, but it feels doubtful we should try to do extra work. It may have... negative security implications if we try to "help" too much.
Ok given the feel expressed here I'll close this issue. Running scripts, etc can be left to a third party crate.
I can add myself to the list of users surprised by this. In Miri we rewrote our ./miri
script in Rust and now we are realizing that this regressed its functionality on Windows; one aspect of that script relied on it spawning itself which no longer works.
On Windows, currently only running
.exe
files is supported and script files aren't. Running.bat
or.cmd
(batch) files may work due to an undocumented feature ofCreateProcessW
(the underlying Windows API call) but it would be good to have proper, documented support rather than relying on undocumented features.Implementing support for batch files would require finding
cmd.exe
ourselves and making sure the arguments passed to the batch file are interpreted as intended.Supporting other types of script file may also be desirable. This can be done by examining the
PATHEXT
environment variable for a list of script file extensions. If the given script file has an extension that matches an entry in this list, then the registry can be used to look up the program to run it.For example, getting the default value from
HKEY_CLASSES_ROOT\.js
will give the default id of the.js
extension ("JSFile"). This id can be used to find the command by getting the default value fromHKEY_CLASSES_ROOT\JSFile\Shell\open\command
. This will return something likeC:\Windows\System32\WScript.exe "%1" %*
where%1
should be replaced with the full path to the script file and%*
should be replaced with any arguments being passed to the script.MSDN documentation