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

ng overwrites/hides Windows Command Prompt title #19205

Closed
15 tasks done
wqoq opened this issue Oct 24, 2020 · 7 comments · Fixed by #23458
Closed
15 tasks done

ng overwrites/hides Windows Command Prompt title #19205

wqoq opened this issue Oct 24, 2020 · 7 comments · Fixed by #23458
Assignees
Labels
2022Q3 Fixit Candidates for the Q3 2022 fix-it area: @ngtools/webpack freq1: low Only reported by a handful of users who observe it rarely severity2: inconvenient type: bug/fix
Milestone

Comments

@wqoq
Copy link

wqoq commented Oct 24, 2020

🐞 Bug report

Command (mark with an x)

  • new
  • build
  • serve
  • test
  • e2e
  • generate
  • add
  • update
  • lint
  • extract-i18n
  • run
  • config
  • help
  • version
  • doc

Is this a regression?

No. As far as I can tell this would have been an issue for as long as Angular CLI has been using process.title = 'something';.

Description

Node's process.title overwrites the entire window title in Windows Command Prompt, which is non-standard behaviour, and makes it very difficult to identify similar windows.

Standard Windows Command Prompt behaviour is to show "{title} - {command}", and this works perfectly if I comment out or remove any reference to process.title, for instance in packages/angular/cli/bin/ng:

// Provide a title to the process in `ps`.
// Due to an obscure Mac bug, do not start this title with any symbol.
try {
  process.title = 'ng ' + Array.from(process.argv).slice(2).join(' ');
} catch (_) {
  // If an error happened above, use the most basic title.
  process.title = 'ng';
}

🔬 Minimal Reproduction

  1. Open a Windows Command Prompt using cmd.exe.
  2. Set the title of the window using the title command (e.g. title My Angular App).
  3. Run any ng command (ng version, ng build --watch, etc...)
  4. While ng is running, the title of the window is completely replaced by whatever ng command was run.

Technically, step 2 is not required to exhibit this bug. I mention it merely to demonstrate why I'm using it (as mentioned in the "Anything else" section below). It happens even with the default title when the window opens.

🌍 Your Environment

From systeminfo:

OS Name:                   Microsoft Windows 10 Enterprise
OS Version:                10.0.18363 N/A Build 18363

From ng version:

Angular CLI: 9.1.1
Node: 13.3.0
OS: win32 x64

Angular: 9.1.1
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router
Ivy Workspace: Yes

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.901.1
@angular-devkit/build-angular      0.901.1
@angular-devkit/build-ng-packagr   0.901.1
@angular-devkit/build-optimizer    0.901.1
@angular-devkit/build-webpack      0.901.1
@angular-devkit/core               9.1.1
@angular-devkit/schematics         9.1.1
@angular/cdk                       9.2.0
@angular/flex-layout               9.0.0-beta.29
@angular/material                  9.2.0
@angular/material-moment-adapter   9.2.0
@ngtools/webpack                   9.1.1
@schematics/angular                9.1.1
@schematics/update                 0.901.1
ng-packagr                         9.0.0
rxjs                               6.5.4
typescript                         3.7.5
webpack                            4.42.0

Anything else relevant?
I assume this only affects Windows. The current behaviour is extremely frustrating because I run multiple apps at the same time, each in a separate window, which I've named "Custom App 1", "Custom App 2", etc..., but once they all start running, each window is identically named "ng build --watch". It's really hard to observe them when I don't know which one is which.

@alan-agius4 alan-agius4 added area: @angular/cli freq1: low Only reported by a handful of users who observe it rarely severity2: inconvenient type: bug/fix labels Oct 24, 2020
@ngbot ngbot bot modified the milestone: Backlog Oct 24, 2020
@wqoq
Copy link
Author

wqoq commented Oct 26, 2020

Actually, I also had to comment out the following use of process.title from ngcc as well, in compiler-cli\ngcc\main-ngcc.js:

    // CLI entry point
    if (require.main === module) {
        // process.title = 'ngcc';    // <--- commented out
        var startTime_1 = Date.now();

Otherwise, the window title would just be the very useless "ngcc".

With those two places commented out, it now works great.

@kyliau kyliau added needs: discussion On the agenda for team meeting to determine next steps and removed needs: discussion On the agenda for team meeting to determine next steps labels Oct 26, 2020
@alan-agius4 alan-agius4 removed freq1: low Only reported by a handful of users who observe it rarely type: bug/fix labels Oct 29, 2020
@ngbot ngbot bot modified the milestones: Backlog, needsTriage Oct 29, 2020
@kyliau
Copy link
Contributor

kyliau commented Nov 2, 2020

@wqoq What is the title when you comment out the code for process.title and run ng commands in Windows command prompt?

We set process.title so that the process is easily identifiable in the Windows Task Manager or MacOS's Activity Monitor.

While we understand that this might not be very useful for you in Windows Command Prompt, it has worked well in other shells and operating systems. Have you explored the option of using a different shell such as PowerShell, Cygwin, or Windows Subsystem for Linux (WSL)?

Since the behavior of setting process.title varies from OS to OS, there's very little we can do to fix this problem. Thanks for your understanding.

@kyliau kyliau closed this as completed Nov 2, 2020
@wqoq
Copy link
Author

wqoq commented Nov 2, 2020

@kyliau I generally run ng in watch mode, so the process stays running.

  1. If I leave all process.title code untouched, my window titles change to "ngcc".
  2. If I comment out the process.title line from ngcc, my window titles change to "ng build {project-name} --watch".
  3. If I comment out the process.title lines from both ngcc and ng, my window titles change to "{window-title} - ng build {project-name} --watch".

So I would argue that using process.title, especially in scenario (1), does not make the process easily identifiable, because I have multiple processes running, all named "ngcc". Which is which? Hopefully you see my problem.

Commenting it out of ngcc, as in scenario (2), gets me some of the way there. I can at least see which project is running in each window.

But I would ideally prefer to run them in scenario (3), where my custom title isn't overwritten.

I don't think switching to another shell is the solution. I just tried Powershell, and the exact same scenarios happen the exact same way. Indeed, process.title is doing exactly as it is designed to do—overwrite the window title. I even opened an issue with Node.js to suggest process.title is doing the wrong thing in Windows, but they disagreed and suggested the problem lies in how each package is using process.title.

If you're aware the behaviour of setting process.title varies from OS to OS, then it seems to me like you shouldn't be using process.title at all. And like I stated originally, things work perfectly if I make it stop using process.title.

Also, FYI, I find it incredibly rude to ask me questions, and then immediately close the issue. Makes me feel like you're not interested in hearing my answers.

@kyliau
Copy link
Contributor

kyliau commented Nov 3, 2020

@wqoq my apologies, I definitely didn't mean it that way.
Based on your description, it looks like we set process.title to ngcc while ngcc was running, but never switch it back to the original title after ngcc is done, and that's the crux of the problem. CLI itself did change the process.title, but as you mentioned, there's minor difference between (2) and (3). I can see how this is annoying. I'll bring this up for discussion with the team.

@kyliau kyliau reopened this Nov 3, 2020
@kyliau kyliau added the needs: discussion On the agenda for team meeting to determine next steps label Nov 3, 2020
@dgp1130
Copy link
Collaborator

dgp1130 commented Nov 6, 2020

Just tested this on my Windows box:

Using WSL with Ubuntu in Windows Terminal, I always saw ng as the title, even when ngcc was running. I think this lines up with what we've seen on *nix systems.

I tried command prompt and PowerShell both in their traditional windows and with Windows Terminal. In all cases, running ng serve on a fresh project showed ng serve, ngcc, and even ngcc (worker) as the window titles. Actually the ngcc (worker) seemed to continue to display, even after ngcc actually completed. That means that running rimraf node_modules\ && npm install && ng serve will settle on ngcc (worker) as the terminal title. Since ngcc only runs the first time though, subsequent ng serve commands will display the title ng serve. It also clobbers a previously set title via the title command, but the title is restored after killing ng serve.

Playing around a little more, I made a simple test Node script to compare the default value of process.title with the title displayed in the terminal UX:

// test.js
console.log(process.title);
setTimeout(() => {}, 5000); // Hang for 5 seconds just to observe terminal title.

And then executed it by setting a custom title first.

In cmd.exe, running title My Custom Title && node test.js displays: My Custom Title - node test.js (note that there are two spaces before the - and between node and test.js, which appear to be completely arbitrary. I observed the same string in the terminal title UX. This is the same in the default window and in Windows Terminal.

In PowerShell, running $host.ui.RawUi.WindowTitle = "My Custom Title"; node test.js displays My Custom Title on its own, with no command line info. this is also the same in Windows Terminal.

In all cases setting process.title = "Foo" will update all title UX display to just "Foo". No shell seems to do anything to format this string.

The NodeJS docs seem to interpret process.title as a means of setting the process name, rather than a terminal title. There's probably some complex history about why these two concepts are coupled, but I don't have context on what that might be.

The UX here is definitely awkward, though I'm not convinced we're doing anything wrong. It seems to me that cmd shell simply sets a default title to <existing-title> - <executed-command>. Once a process overwrites that value, the existing title is lost. PowerShell doesn't set this default and Unix doesn't either, so it seems to be an idiosyncrasy of cmd in particular. Even if we changed our usage of process.title, I don't think we can conditionalize on if (runningInCmdButNotPowerShell()) { /* ... */ }. Our options would either be 1) leave as is, 2) don't set process.title on Windows at all, meaning Task Manager would list it as node and PowerShell would still be different from cmd.

I see four distinct bugs which are potentially actionable to create the behavior you want.

  1. Update cmd to always append a new process title to any previous title invocation.
    • This means that running title Foo && node -e "process.title = 'Bar';" would yield Foo - Bar. How a title gets displayed is the cmd shell's decision.
  2. Update Windows Terminal to always append a new process title to any previous title invocation.
    • This is arguably a terminal bug rather than shell bug as it has to do with the UX of a label. Although I'm not entirely sure where the line is between cmd and Windows Terminal with regard to the window title. title Foo and node -e "process.title = 'Foo';" may be indistinguishable to Windows Terminal.
    • This wouldn't help with cmd.exe however.
  3. Updates cmd to "pop" child process titles.
    • ngcc (worker) sticks around after it has died, which is pretty weird. I'm guessing cmd is using a "last one wins" mentality when it should probably use a "last one from a still-alive process wins".
  4. Re-set process.title = 'ng serve ...'; after ngcc completes.
    • This can actually be done by Angular, and would fix the ngcc (worker) problem, but it is definitely hack and makes no logical sense that we would need to do that.

Fundamentally, the problem here is that process.title refers to both the process title and the terminal title, despite these being two distinct strings which may want to be different things. cmd further complicates this by behaving differently that other shells and giving a default value which (while convenient) is not a persistent format as the title is changes from subprocesses. Based on this, I'm not convinced our current usage of process.title is wrong or that anything necessarily needs to be changed there.

@dgp1130
Copy link
Collaborator

dgp1130 commented Nov 12, 2020

We discussed these findings in our team meeting and our consensus is that this is mostly a cmd bug. We can only set the process name, not the terminal title. So it is up to the terminal environment to decide how to display that as a title. cmd is just a bit inconsistent between its default value and what it displays after a new value is set. We also can't really distinguish whether we are invoked from cmd or PowerShell, and they have different title behavior in this regard.

There is definitely a usability issue here, particularly around displaying ngcc (worker). As a result, we do believe option 4. is worth doing. It shouldn't be necessary to re-set process.title and is indicative of a bug in cmd, but it is pretty easy to do, is harmless to other terminal emulators, and gives a more meaningful title to users.

@dgp1130 dgp1130 removed the needs: discussion On the agenda for team meeting to determine next steps label Nov 12, 2020
@alan-agius4 alan-agius4 added area: @ngtools/webpack freq1: low Only reported by a handful of users who observe it rarely and removed area: @angular/cli labels Nov 12, 2020
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Nov 12, 2020
@alan-agius4 alan-agius4 added the 2022Q3 Fixit Candidates for the Q3 2022 fix-it label Jun 28, 2022
alan-agius4 added a commit to alan-agius4/angular-cli that referenced this issue Jun 28, 2022
More context about this can be found in the following comment: angular#19205 (comment)

Closes angular#19205
@alan-agius4 alan-agius4 self-assigned this Jun 28, 2022
clydin pushed a commit that referenced this issue Jun 28, 2022
More context about this can be found in the following comment: #19205 (comment)

Closes #19205
clydin pushed a commit that referenced this issue Jun 28, 2022
More context about this can be found in the following comment: #19205 (comment)

Closes #19205

(cherry picked from commit 7ababc2)
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jul 29, 2022
ikjelle pushed a commit to ikjelle/angular-cli that referenced this issue Mar 26, 2024
More context about this can be found in the following comment: angular#19205 (comment)

Closes angular#19205
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
2022Q3 Fixit Candidates for the Q3 2022 fix-it area: @ngtools/webpack freq1: low Only reported by a handful of users who observe it rarely severity2: inconvenient type: bug/fix
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants