Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd: add environment variable to disable/enable 'Terminate batch job (Y/N)?' confirmation #217

Open
mikemaccana opened this issue Jul 7, 2018 · 67 comments
Labels
Area-Interaction Interacting with the vintage console window (as opposed to driving via API or hooks) Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Cmd.exe The issue is related to the legacy command interpreter, CMD.exe.
Milestone

Comments

@mikemaccana
Copy link
Contributor

(migrated from PowerShell/PowerShell#7080 per @BrucePay's suggestion)

When I cancel a cmd script with Ctrl C, the following dialog pops up:

Terminate batch job (Y/N)?

I understand why this exists, but I'd also like the option to disable it, so cancelling cancels immediately. Judging by Stack Overflow, I'm not the only one

So a request: could we have an environment variable to control this?

@zadjii-msft
Copy link
Member

@paulcam206 as the cmd guru, he'll probably have more thoughts on the matter.

I really highly doubt that we could just add an env var to disable this, but it is an interactive-only scenario, so it might be possible...

@zadjii-msft zadjii-msft added Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Cmd.exe The issue is related to the legacy command interpreter, CMD.exe. labels Jul 9, 2018
@mikemaccana
Copy link
Contributor Author

Thanks for responding Mike! Any specific reason why checking a flag would be so difficult? Looking forward to seeing what @paulcam206 thinks.

@zadjii-msft
Copy link
Member

Honestly, changing cmd.exe at all is a bit terrifying. You can't be sure who in the world is actually depending on that behavior for some reason or another.

relevant xkcd

@paulcam206
Copy link
Member

it's possible that this could be done with something like a new setlocal setting. however, we've not added one of these in a long time. that said, I'll file an item on our backlog to investigate :)

@mikemaccana
Copy link
Contributor Author

mikemaccana commented Jul 11, 2018

Ack @zadjii-msft - not proposing to change the default, so should only affect people who've explicitly set some very long string.

@paulcam206 thanks! I'm not sure about how setlocal works - my real experience of cmd is launching cmd files from powershell). Would I still be able to do this in Powershell:

$env:TERMINATE_IMMEDIATELY='yes'
somefile.cmd

Then press Ctrl C when I need to and have it work?

@miniksa
Copy link
Member

miniksa commented Jul 11, 2018

setlocal doesn't behave the same way as an environment variable. It's a thing that would have to be put in at the top of the batch script that is somefile.cmd as one of its first commands to adjust the way that one specific batch file is processed by the cmd.exe engine. That's probably not suitable for your needs, but that's the way we have to go.

I don't think anyone is disagreeing with you, @mikemaccana, that this would be a five minute development change to read that environment variable and change the behavior of cmd.exe. It absolutely would be a tiny development time.

It's just that from our experience, we know there's going to be a 3-24 month bug tail here where we get massive investigation callbacks by some billion dollar enterprise customer who for whatever reason was already using the environment variable we pick for another purpose. Their script that they give their rank-and-file folks will tell them to press Ctrl+C at some point in the batch script to do whatever happens, it will do something different, those people will notice the script doesn't match the computer anymore. They will then halt the production line and tell their supervisor. The supervisor tells some director. Their director comes screaming at their Microsoft enterprise support contract person that we've introduced a change to the OS that is costing them millions if not billions of dollars in shipments per month. Our directors at Microsoft then come bashing down our doors angry with us and make us fix it ASAP or revert it, we don't get to go home at 5pm to our families or friends because we're fixing it, we get stressed the heck out, we have to spin up servicing potentially for already shipped operating systems which is expensive and headache-causing...etc.

We can see this story coming a million miles away because it has happened before with other 'tiny' change we've been asked to make to cmd.exe in the past few years.

I would just ask you to understand that cmd.exe is very, very much in a maintenance mode and I just want to set expectations here. We maintain it, yes. We have a renewed interest in command-line development, yes. But our focuses are revolving around improving the terminal and platform itself and bringing modern, supported shells to be the best they can be on Windows. Paul will put this on the backlog of things that people want in cmd.exe, yes. But it will sink to the bottom of the backlog because changing cmd.exe is our worst nightmare as its compatibility story is among the heaviest of any piece of the operating system.

I would highly recommend that Gulp convert to using PowerShell scripts and that if such an issue exists with PowerShell, that we get their modern, supported, and better-engineered platform to support the scenario. I don't want you to sit around waiting for cmd.exe to change this because it's really not going to happen faster than that script could be converted to ps1 and it fixed in PowerShell Core (if that's even a problem in that world.)

@zadjii-msft
Copy link
Member

oh god I'm having ptsd flashbacks just reading that

@paulcam206
Copy link
Member

yep

@bitcrazed
Copy link
Contributor

bitcrazed commented Jul 11, 2018

@ALL - @miniksa @zadjii-msft and @paulcam206 are not kidding - the unexpected impact of even the smallest change to Cmd has resulted in calamities, misfortune, lost-weekends and evenings, stress and unnecessary turmoil.

Cmd is in maintenance mode. It isn't being deprecated or removed - in fact, I doubt it'll EVER be removed from Windows, but do understand that Cmd is extremely fragile and difficult to change.

I keep saying it, and now that PowerShell is available almost everywhere - even Linux & macOS - it's more true than ever:

If you're writing Windows Command-Line scripts today, they should be PowerShell scripts wherever possible

@mikemaccana
Copy link
Contributor Author

mikemaccana commented Jul 13, 2018

Thanks @bitcrazed. I appreciate the testimony directly from the horse's mouth - I've submitted a PR to one of the many node projects that use cmd scripts, with a .ps1 replacement. Hopefully it gets accepted and we start moving node onto a more supported scripting language.

@parkovski
Copy link

parkovski commented Jul 13, 2018

It seems to me that cmd scripts are generally used in the place of exe symlinks and shebang scripts, which PowerShell is not a good replacement for - if you switch out yarn.cmd for yarn.ps1, that's fine if you're already in PowerShell, but if you're in cmd, or some other shell, or using ShellExecute or some scripting language's equivalent, you have to write pwsh -c yarn, so then why not get rid of the script altogether and do node yarn.js?

For this type of thing, we're pretty much stuck with something in PATHEXT, and I think cmd is the only console interpreter in there.

@mikemaccana
Copy link
Contributor Author

mikemaccana commented Jul 16, 2018

Powershell is just as good as cmd here. If you're calling yarn.js from some other language of course you'd run node yarn.js, whether yarn comes with yarn.cmd or yarn.ps1. The point is you can type yarn from the command line (which in Windows is powershell) and it runs yarn, and when something goes wrong you don't have to debug something which isn't maintained anymore. I've replied on yarnpkg/yarn#6093 with more info - it may be best to move the discussion there.

@parkovski
Copy link

parkovski commented Jul 16, 2018

Well, relevant to this thread, adding the setlocal option is just as good and addresses my concerns also - then all the projects that use cmd scripts this way just add another line at the top.

It still requires projects to opt into this behavior, and it's not compatible with older versions of Windows (well, it's compatible, just ignored), but it seems like the best way to do this to me. Doesn't break any other cmd scripts assuming yarn is a command, and I'd be happy replacing my hacked together exe launcher with these.

The point is you can type yarn from the command line (which in Windows is powershell)

With all the recent console improvements and WSL, I think there's a possibility of seeing alternate shells on Windows in the future. Cmd may be in maintenance mode, but people still use it too, so I'm not a huge fan of this assumption.

Personally I'd really like to see the setlocal option, regardless of how projects choose to handle this.

@xenu
Copy link

xenu commented Jul 25, 2018

It seems to me that cmd scripts are generally used in the place of exe symlinks and shebang scripts, which PowerShell is not a good replacement for

It's true. For example, perl wraps all scripts installed from cpan with a few lines of batch code loading perl executable using its pl2bat script.

setlocal variant would be very helpful for perl because it would allow us to fix Terminate batch job (Y/N)? issue by making pl2bat add setlocal line to scripts generated with this tool .

@be5invis
Copy link

@bitcrazed
But, executing PowerShell script is not enabled by default.

@be5invis
Copy link

@parkovski
An interesting idea would be using WSF/WSH files.

@Jack-Works
Copy link

Any progress on this issue?

@zadjii-msft
Copy link
Member

cmd.exe is very, very much in a maintenance mode and I just want to set expectations here. We maintain it, yes. We have a renewed interest in command-line development, yes. But our focuses are revolving around improving the terminal and platform itself and bringing modern, supported shells to be the best they can be on Windows.

We're not going to make changes to cmd.exe to support this scenario.

@Jack-Works
Copy link

cmd.exe is very, very much in a maintenance mode and I just want to set expectations here. We maintain it, yes. We have a renewed interest in command-line development, yes. But our focuses are revolving around improving the terminal and platform itself and bringing modern, supported shells to be the best they can be on Windows.

We're not going to make changes to cmd.exe to support this scenario.

Okay, I understand this.
But, is there an unofficial / hack solution to this?
I searched the web and only found someone patching binary to do this.
Unfortunately, that only works for Windows XP to and Windows 7

Then I found another project, https://github.com/sgraham/cmdEx
Only works for Windows 8.1 32bit

:(

@be5invis
Copy link

be5invis commented Apr 2, 2019 via email

@miniksa
Copy link
Member

miniksa commented Apr 2, 2019

@Jack-Works, we are not in the business of developing or propagating unofficial hacks to our software. If you figure something out, more power to you. But we can't help you there.

@be5invis, I'm sure the Powershell team would be happy to accept your feedback and improve their product. They are the Microsoft team that has funding for the interactive shell space.

@mikemaccana
Copy link
Contributor Author

As everyone else says, the fix for this is moving from cmd to ps1. @bitcrazed mentioned he's going to publish a blog post recommending people do this a little while ago (since a lot of node folks etc are producing new cmd scripts).

While we wait for peopel to start distributing ps1 scripts, the safest bet to handle leftover cmds is to etiher press Ctrl C twice or use something like Hyper's https://hyper.is/plugins/hyper-yes

@musm
Copy link

musm commented Apr 11, 2019

I agree with the problem with using powershell here instead of cmd; which I agree would be ideal, except it's far too slow in its initialization time. Even more unfortunately the new pwsh is even slower to initialize. This is something I opened an issue about, but the situation is not likely to be improved PowerShell/PowerShell#6443.

Startup latency:
466 ms POWERSHELL
42 ms CMD

500 ms is way too long for a script, hence I'm not sure the solution to use ps1 is actually reasonable.

Here's the script to test start up latency

> function time($block) {
    $sw = [Diagnostics.Stopwatch]::StartNew()
    &$block
    $sw.Stop()
    $sw.Elapsed
}

> time {powershell -NoProfile -c exit}
> time {cmd-NoProfile -c exit}

@haseakash

This comment has been minimized.

@noseratio
Copy link

It appears like nobody wants to approach cmd.exe and touch it with a stick, because "we can break something". So cmd.exe has been in "maintenance mode", while its legitimate use keeps growing due to the popularity of CLI tools like Node.js, NPM, Deno etc., which heavily rely upon .CMD and .BAT files on Windows.

I struggle to come up with even a contrived scenario where the proper Ctrl+C handling (especially behind a feature flag) could possibly break any legacy scripts. OTOH, I can think of a magnitude of cases where the current behavior causes annoyances and harm.

E.g., when the following batch file is executing and I hit Ctrl+C trying to stop it, the infamous "Terminate batch job (Y/N)?" prompt is shown. I hit Ctrl+C again to escape, but the execution is continuing instead, deleting my GIF files:

@echo off
echo About to delete *.gif. Press Ctrl+C to stop
pause
del /q *.gif

For a more convincing example, speak to this person:

image

Luckily, there's new CreatePseudoConsole Win32 API that should make possible to create a proper shim for cmd.exe, to look for and intercept the "Terminate batch job (Y/N)?" prompt. Such shim can then be set as an active command shell via COMSPEC env variable.

When time allows, I'm going to explore this options, like I did to address another controversial behavior, paste-with-formatting-by-default.

@miniksa
Copy link
Member

miniksa commented Nov 3, 2021

It appears like nobody wants to approach cmd.exe and touch it with a stick, because "we can break something". So cmd.exe has been in "maintenance mode", while its legitimate use keeps growing due to the popularity of CLI tools like Node.js, NPM, Deno etc., which heavily rely upon .CMD and .BAT files on Windows.

I struggle to come up with even a contrived scenario where the proper Ctrl+C handling (especially behind a feature flag) could possibly break any legacy scripts. OTOH, I can think of a magnitude of cases where the current behavior causes annoyances and harm.

E.g., when the following batch file is executing and I hit Ctrl+C trying to stop it, the infamous "Terminate batch job (Y/N)?" prompt is shown. I hit Ctrl+C again to escape, but the execution is continuing instead, deleting my GIF files:

@echo off
echo About to delete *.gif. Press Ctrl+C to stop
pause
del /q *.gif

For a more convincing example, speak to this person:

image

Luckily, there's new CreatePseudoConsole Win32 API that should make possible to create a proper shim for cmd.exe, to look for and intercept the "Terminate batch job (Y/N)?" prompt. Such shim can then be set as an active command shell via COMSPEC env variable.

When time allows, I'm going to explore this options, like I did to address another controversial behavior, paste-with-formatting-by-default.

This specific issue came in through Feedback Hub as well and I spent some time reproducing it. When I use conhost.exe, the first time I run the contrived script and do Ctrl+C twice, it exits properly. But subsequent runs, it deletes at the second one anyway. And when through Terminal... it just immediately goes to the second state and deletes.

So you've hit my interest further and I will be pulling this particular case out into a separate bug to figure out why the state changes and differs.

EDIT: MSFT:36733663

@eryksun
Copy link

eryksun commented Nov 4, 2021

When I use conhost.exe, the first time I run the contrived script and do Ctrl+C twice, it exits properly. But subsequent runs, it deletes at the second one anyway. And when through Terminal... it just immediately goes to the second state and deletes.

Canceling the batch termination prompt uses no as the default answer, and thus the script continues to run. In particular, cmd!PromptUser() handles a failed/canceled or empty (EOF) read by defaulting the answer to no. That's reasonable behavior in the general case (e.g. do not delete all the files in the "foo" directory for del foo). For the batch termination prompt, it probably would have been more reasonable to handle repeated Ctrl+C presses by terminating the script instead of canceling the prompt itself. (I'm thinking of a user frantically pressing Ctrl+C.) A parameter could have been added to PromptUser() to set the default answer instead of hard coding no as the default.

@simonbuchan
Copy link

If MSFT is still watching this... what's the likelihood of being able to add a stub-specific replacement, and a new default entry to PATHEXT? I'm thinking the .cmd stub builders of the world like npm can instead emit a .some-stub-ext file that contains some trivial format like:

cd ..\..\some-package
exec node.exe
arg --some-option
forward-args
arg --
arg another-option

If it's part of windows, runs very fast, doesn't alter cmd.exe etc., that seems to mostly fix people's issues in this thread. It's mostly the change to the PATHEXT default that seems scary.

@simonbuchan
Copy link

Notably, .lnk files cover a lot of that usage, and seems to work quite well if you add them to PATHEXT. Are there issues with using .lnk as stubs?

@zadjii-msft zadjii-msft added this to the Backlog milestone Aug 22, 2022
@doctorpangloss
Copy link

doctorpangloss commented Oct 27, 2023

@zadjii-msft can you hear the people chanting "Terminate batch job (Yes/No) has got to go!"?

One option is to break cmd.exe, forcing all shims to be authored anew. Because the prompt is kind of on the journey there already.

It's just that from our experience, we know there's going to be a 3-24 month bug tail here where...

Yeah. But like those people will keep using Windows, as much as you break it for them, but the people in this thread will keep switching to macOS. Kind of apples to oranges. It's been 5 years.

@zadjii-msft
Copy link
Member

You're heard, for sure. But we're not planning on touching cmd.exe. Literally last week we had a P0 fire where we broke the core Windows build because we tried making what seemed like a trivial internal change to the CMD.exe code. It's literally burned us 100% of the times we've tried to touch it.

If you want a modern, updated shell on Windows, you should try out PowerShell 7. Or clink. Or yori.

@oising
Copy link
Collaborator

oising commented Oct 27, 2023

You're heard, for sure. But we're not planning on touching cmd.exe. Literally last week we had a P0 fire where we broke the core Windows build because we tried making what seemed like a trivial internal change to the CMD.exe code. It's literally burned us 100% of the times we've tried to touch it.

If you want a modern, updated shell on Windows, you should try out PowerShell 7. Or clink. Or yori.

This would make a super interesting blog post (which you could point people to any time they ask this again) -- maybe ping Raymond Chen? :D

@doctorpangloss
Copy link

I use https://frippery.org/busybox/

It's literally burned us 100% of the times we've tried to touch it.

Would it be possible to release the source of cmd.exe? Is it even that sensitive? Lemme pitch the metric: "Number of cmd.exes open sourced." An increase in this metric from 0 to 1, it's +infinity percent!

I got you, thanks for the kind note.

@noseratio
Copy link

noseratio commented Oct 28, 2023

You're heard, for sure. But we're not planning on touching cmd.exe. Literally last week we had a P0 fire where we broke the core Windows build because we tried making what seemed like a trivial internal change to the CMD.exe code. It's literally burned us 100% of the times we've tried to touch it.

If you want a modern, updated shell on Windows, you should try out PowerShell 7. Or clink. Or yori.

Sadly, many popular CLI/DevOps tools (Node.js, NPM, Chromium build, etc) already use CMD on Windows, and that's not gonna change, they won't switch to PowerShell.

The fear of changing CMD to actually terminate upon Ctrl+C is not only irrational, but also dangerous.

E.g., like I mentioned previously in this thread, the following will delete all .gif files, when I franticly press Ctrl+C two times while trying to stop it. It's just beyond my comprehension.

@echo off
echo About to delete *.gif. 
pause
del /q *.gif

At least, it it possible to make the second Ctrl+C act as Y when CMD is already asking Terminate batch job (Y/N)?

What do you think about that, @zadjii-msft?

@skissane
Copy link

I understand why you are terrified of changing anything in cmd.exe.

But:

  1. Define a brand new registry value (or even a whole new key) which nobody is using–if you are truly paranoid about the chance someone already has it set, put it somewhere unrelated to the registry keys cmd.exe already looks at, even put a random GUID in the key or value name so the chance that it already exists is astronomically low
  2. At cmd.exe startup, check if that registry value exists and has the value 1, and if so set an internal boolean flag
  3. If the boolean flag is set, skip displaying the Terminate batch job (Y/N)? prompt, act as if Y was answered. This is likely just one extra if statement (if that)

That way, people who want to make this prompt go away, can create the new registry key/value.

It is rather difficult to conceive of a way in which the above change could possibly break anything. If the registry key/value isn't set, it behaves identically to at present. If setting it breaks something, the solution is to remove that registry setting.

@andry81
Copy link

andry81 commented Mar 13, 2024

@skissane

  1. Define a brand new registry value

Bad idea. It will affect all cmd.exe instances. Better, for example, to extend setlocal with a new flag like:
setlocal DISABLECTRLBREAKINTERACTION

@noseratio

This comment has been minimized.

@oising
Copy link
Collaborator

oising commented Mar 13, 2024

@skissane said:

It is rather difficult to conceive of a way in which the above change could possibly break anything.

With these words, you explain exactly why this change is so insidiously dangerous.

@noseratio
Copy link

With these words, you explain exactly why this change is so insidiously dangerous.

Can it get any worse than data loss, caused by the existing behavior, when it simply continues if you hit Ctrl+C twice? Someone deleted the whole database! 🥲

As is, it's not just annoying, it's dangerous enough already.

@oising
Copy link
Collaborator

oising commented Mar 14, 2024

With these words, you explain exactly why this change is so insidiously dangerous.

Can it get any worse than data loss, caused by the existing behavior, when it simply continues if you hit Ctrl+C twice? Someone deleted the whole database! 🥲

As is, it's not just annoying, it's dangerous enough already.

I don't disagree, but somebody, somewhere, is depending on this behaviour.

@noseratio

This comment was marked as off-topic.

@anonghuser
Copy link

anonghuser commented Aug 7, 2024

I can see how changing the default behavior of cmd or its pause may burn someone, but adding a new command-line switch to pause to make it set errorlevel when interrupted or an optional, opt-in mode to cmd should not be an issue.
(edit: "opt-in mode to cmd" = setlocal yes, don't know why @miniksa said it's "probably not suitable for your needs", seems perfect for mine)

Failing that, please at least make powershell pause || exit not wreck cmd's font...

@noseratio

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Interaction Interacting with the vintage console window (as opposed to driving via API or hooks) Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Cmd.exe The issue is related to the legacy command interpreter, CMD.exe.
Projects
None yet
Development

No branches or pull requests