12

I have a debug launch configuration (launch.json) like below.

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Current TS File",
            "type": "node",
            "request": "launch",
            "preLaunchTask": "Pre Debug Task",
            "postDebugTask": "Stop Watch Styles",
            "args": ["${relativeFile}"],
            "runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
            "sourceMaps": true,
            "cwd": "${workspaceRoot}",
            "protocol": "inspector",
        }
    ]
}

My tasks configuration (tasks.json) is like

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "npm",
            "script": "next:copy",
            "label": "Copy Files",
            "problemMatcher": []
        },
        {
            "type": "npm",
            "script": "styles:tsw",
            "label": "Watch Styles",
            "problemMatcher": [],
        },
        {
            "label": "Pre Debug Task",
            "isBackground": true,
            "dependsOn" :[
                "Copy Files",
                "Watch Styles"
            ]
        },
        {
            "label": "Stop Watch Styles",
            // No sure what should come here
        }
    ]
}

Trying to stop watch process in postDebugTask, is there a way to Terminate Task by providing name (Watch Styles) as parameter in tasks.json. Watch styles is a continuously running process, please suggest if there is any other approach to terminate a task after debugging is complete.

Mark
  • 143,421
  • 24
  • 428
  • 436
Sandeep Kumar
  • 1,758
  • 1
  • 22
  • 39

5 Answers5

22

This will terminate all tasks after debug stops

Or in this case, just build_runner watch...

launch.json

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Flutter",
      "request": "launch",
      "type": "dart",
      "flutterMode": "debug",
      "preLaunchTask": "flutter: build_runner watch",
      "postDebugTask": "Terminate All Tasks"
    }
  ]
}

tasks.json

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Terminate All Tasks",
      "command": "echo ${input:terminate}",
      "type": "shell",
      "problemMatcher": []
    }
  ],
  "inputs": [
    {
      "id": "terminate",
      "type": "command",
      "command": "workbench.action.tasks.terminate",
      "args": "terminateAll"
    }
  ]
}

More info here: https://code.visualstudio.com/docs/editor/variables-reference#_command-variables

Daniel M.
  • 3,225
  • 1
  • 22
  • 16
  • 1
    This kind of works, but doesn't close the associated terminal after terminating the task. Any ideas? I'm running `php artisan serve` command in the task btw. – dotNET Oct 29 '22 at 07:42
4

This works for me:

{
   "label": "postdebugKill",
   "type": "process",
   "command":[
      "${command:workbench.action.tasks.terminate}",
      "${command:workbench.action.acceptSelectedQuickOpenItem}",
   ],
},

The first "${command:workbench.action.tasks.terminate}" will bring up a panel asking you to select which task to terminate. So if you had multiple running tasks and wanted to choose one you would use this command only.

The second "${command:workbench.action.acceptSelectedQuickOpenItem}" will terminate the selected task in that panel mentioned above. (So you will not even see the terminate panel.) If you have only one running task when you call the postdebugKill task, it will be selected automatically and thus terminated. Otherwise whichever task is listed first will be terminated. Again, if you have more than one other task running and you want to select which to terminate don't include this second command.

I don't know of any way to list, perhaps via an args option a label name for which task to terminate if running. It would be nice to have this functionality.

[postdebugKill name can be whatever you want.]

To call a postdebug task your launch.json config might look like this:

{
   "type": "node",
   "request": "launch",
   "name": "Gulp: serve",
   "program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
   "args": [
     "serve"
   ],

   //  "preLaunchTask": "someTask",

   "postDebugTask": "postdebugKill"
},

Upon stopping that "Gulp: serve" debugging session, the task "postdebugKill" will be triggered. And so if I had used the "preLaunchTask" to start a task or had simply started a task running before launching the "Gulp: serve" debugging session - that preLaunchTask would be terminated.

The ability to run vscode commands in a task was recently added to vscode. Some minimal info here: using a command in a task doc.

Mark
  • 143,421
  • 24
  • 428
  • 436
  • Thanks for your response. What is your version of VS Code. My version is 1.29.1, I tried adding the commands in post debug section, for me it didn't prompt to ask task to be terminated. I saw statement in terminal. I am stopping debug task via Shift+F5 or using Stop icon for debug `> Executing task in folder my-app-folder: C:\Users\sandeep\Codebase\my-app-folder\${command:workbench.action.tasks.terminate} ${command:workbench.action.acceptSelectedQuickOpenItem}` – Sandeep Kumar Feb 04 '19 at 06:56
  • I am using 1.30.2. I have done some research and I'll put it into a separate answer. – Mark Feb 05 '19 at 04:13
  • When I try to run this task manually VS Code just opens a terminal and logs `The terminal shell path "${command:workbench.action.tasks.terminate} ${command:workbench.action.acceptSelectedQuickOpenItem}" does not exist`. I'm using VS Code version 1.42.1 – knee-cola Feb 20 '20 at 07:53
  • 2
    The second command `"${command:workbench.action.acceptSelectedQuickOpenItem}"`doesn't seem to have an effect. Upon stopping the debugger vscode is asking me to confirm which running script to select for the first command. – maninak Feb 01 '23 at 00:59
2

[I'll add another answer because the new additional info is extensive.]

It seems there is an issue with running a preLaunchTask and then launching a debugging session. See particularly debugging does not work on first try. It appears to be fixed though in an insiders edition and may be released in early February 2019. terminal not sending onLineData.

In the meantime there is a suggested fix within one of the issues that I have lost the link to and that is a problemMatcher which will signal to the debugger that the dependent tasks have completed.

In my watching task I used this:

"problemMatcher": [
   {
     "base": "$tsc-watch",
     "background": {
       "activeOnStart": true,
       "beginsPattern": "Using gulpfile ~\\OneDrive\\experimental\\gulpfile.js",
       "endsPattern": "Starting 'watch'..."
     }
   }
],

I chose that because when I manually start the gulp:watch task I get this in the terminal:

[22:27:48] Using gulpfile ~\OneDrive\experimental\gulpfile.js
[22:27:48] Starting 'watch'...
[22:27:48] Starting 'watch'...

So you see the start and end pattern there that I copied (with extra escaping).

I suggest that you separately run your "Pre Debug Task" and copy the start and ending output into your "Pre Debug Task" problemMatcher and see if it now works.

My code in the first answer I believe is correct, I just wasn't using "isBackground" and "dependsOn" as you are. But I have added "isBackground" to mine and the problemMatcher option and it works flawlessly now.

Hopefully, this will be fixed in the next February 2019 release and there will be no need for this workaround.

Mark
  • 143,421
  • 24
  • 428
  • 436
  • Thanks Mark for taking time, I would need to check my watch task, trying to identify pattern which can be put into problemMatcher. I wish this was simpler :). Probably I would wait for separate answer which you suggested you are giving. – Sandeep Kumar Feb 05 '19 at 09:51
  • That was the second answer. This "might" be fixed as soon as Feb. 6, 2019 when the next update to vscode may be released. – Mark Feb 05 '19 at 14:38
2

If on Linux or macOS, a less hacky solution that just works is using pkill. If on Windows, see below.

First run the task and find the full command vscode runs for that task, with $ ps -af

Then use pkill + the full command in a postDebugTask.

I have an entry in tasks.json like this:

{
    "label": "stop npm:watch",
    "type": "shell",
    "command": "pkill -f 'sh -c node ./scripts/watch.js'",
    "presentation": {
        "reveal": "silent",
        "panel": "dedicated",
        "close": true,
    }
}

'sh -c node ./scripts/watch.js' is how vscode runs my npm:watch task.

The presentation properties prevent this task from taking focus or taking up terminal space after it finishes successfully.

Then you reference that task in a launch.json configuration:

{
    ...
    "preLaunchTask": "npm:watch",
    "postDebugTask": "stop npm:watch",
    ...
}

If the full command contains changing parameters (paths, port numbers, etc.), you can use a part of the command or regex.

e.g.: I could have probably matched with './scripts/watch.js' or 'node.*watch'.


For Windows: you can make this work by substituting pkill for taskkill.

If you want to support both Unix and Windows, you can make a script that does one or the other depending on the underlying OS.

victor-gp
  • 68
  • 1
  • 6
0

This is what came up with for my Vite+React+Typescript project; I wanted to kill the dev server automatically when I stop the debugger.
tasks.json -

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "npm dev", // the name of the task to be executed when I press'F5'. The 'terminate' command terminates this task.
      "isBackground": true,
      "type": "npm",
      "script": "dev",
      "problemMatcher": {
        "owner": "typescript",
        "fileLocation": "relative",
        "pattern": {
          "regexp": "^([^\\s].*)\\((\\d+|\\,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$",
          "file": 1,
          "location": 2,
          "severity": 3,
          "code": 4,
          "message": 5
        },
        "background": {
          "activeOnStart": true,
          "beginsPattern": "^.*env-management-ui@0.0.0 dev.*",
          "endsPattern": "^.*VITE v4.4.7  ready in.*",
        },
      },
    },
    {
      "label": "terminate dev server",
      "command": "echo ${input:terminate}", // the 'terminate' command that's defined in the inputs list
      "type": "shell",
      "problemMatcher": []
    }
  ],
  "inputs": [
    {
      "id": "terminate",
      "type": "command",
      "command": "workbench.action.tasks.terminate",
      "args": "npm dev" // the name of the task to be terminated when the 'terminate' command is executed.
    }
  ]
}

launch.json -

{
    "configurations": [
        {
            "type": "msedge",
            "request": "launch",
            "name": "Launch Edge against localhost",
            "url": "http://localhost:5173",
            "webRoot": "${workspaceFolder}",
            "skipFiles": [
                "${workspaceFolder}/node_modules/**/*.js"
            ],
            "preLaunchTask": "npm dev",
            "postDebugTask": "terminate dev server",
        },
    ],
}

Explanation:
In tasks.json I defeined the following task terminate dev server:

{
      "label": "terminate dev server",
      "command": "echo ${input:terminate}",
      "type": "shell",
      "problemMatcher": []
}

The task receives the terminate input, which is defined in the inputs list:

"inputs": [
    {
      "id": "terminate",
      "type": "command",
      "command": "workbench.action.tasks.terminate",
      "args": "npm dev"
    }
]

The terminate input's command gets the name of the task to be terminated as args; in my case, the name is npm dev, which is the label of the first task in my tasks list. To view all the currently running tasks, press CTRL+SHIT+P in VS Code, then search for Tasks: Terminate Task. Clicking it will show a dropdown with all the currently running tasks.

In launch.json I defined the npm dev task as my preLaunchTask, and the terminate dev server task as my postDebugTask. So when I hit F5, the preLaunchTask is executed, running the dev server and opening my browser with a debugger attached. Then, when I stop the debugger, the postDebugTask is executed, terminating my preLaunchTask.

Elyasaf755
  • 2,239
  • 18
  • 24