59

I have a debug setup in Visual Studio code where I run an external binary which can execute my JS files (using duktape). The debug adapter currently only supports attach requests (not launch) so I have to run the binary before I can debug the JS scripts.

In order to avoid having to start the application manually I created a task for it and set that in my launch.json file:

{
    "version": "0.2.0",
    "configurations": [{
        "name": "Attach MGA",
        "type": "duk",
        "preLaunchTask": "debug mga",
        "request": "attach",

        "address": "localhost",
        "port": 9091,

        "localRoot": "${workspaceRoot}",

        "stopOnEntry": false,
        "debugLog": true
    }]
}

The task is defined so:

{
    "version": "0.1.0",
    "command": "<absolute path to>/mga",
    "isShellCommand": false,
    "showOutput": "always",
    "suppressTaskName": true,
    "tasks": [{
        "taskName": "debug mga",
        "args": ["--debugger", "main.json"]
    }]
}

The problem is now that vscode waits for the pre launch task to finish, while the application waits for a debugger to attach. Catch 22.

How can I avoid that vscode waits for the pre launch task to finish?

Update:

Meanwhile I have read up on the vscode task page and came up with this task configuration. Still, it doesn't work for me

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "launch-mga",
            "type": "shell",
            "command": "<absolute path to>/mga",
            "args": [
                "config/main.json",
                "--debugger"
            ],
            "isBackground": true,
            "problemMatcher": {
                "owner": "custom",
                "pattern": {
                    "regexp": "_____"
                },
                "background": {
                    "activeOnStart": true,
                    "beginsPattern": "^.*Waiting for debug connection.*$",
                    "endsPattern": "^.*blah.*$"
                },
            },
        }
    ]
}

The launched application prints the wait message and then waits endlessly for a debug connection. Maybe the problem has to do with the application (which is kinda Node.js like terminal app), written in C++?

Mike Lischke
  • 48,925
  • 16
  • 119
  • 181

5 Answers5

62

This worked for me.

Note all these are required, even though none are important:

  • problemMatcher.pattern.regexp
  • problemMatcher.pattern.file
  • problemMatcher.pattern.location
  • problemMatcher.pattern.message
  • problemMatcher.background.activeOnStart
  • problemMatcher.background.beginsPattern
  • problemMatcher.background.endsPattern
{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "label": "build-extras",
      "type": "shell",
      "isBackground": true,
      "command": "./script/build-extras",

      // This task is run before some debug tasks.
      // Problem is, it's a watch script, and since it never exits, VSCode
      // complains. All this is needed so VSCode just lets it run.
      "problemMatcher": [
        {
          "pattern": [
            {
              "regexp": ".",
              "file": 1,
              "location": 2,
              "message": 3
            }
          ],
          "background": {
            "activeOnStart": true,
            "beginsPattern": ".",
            "endsPattern": ".",
          }
        }
      ]
    }
  ]
}
mike wyatt
  • 1,280
  • 11
  • 13
  • 2
    It's true! You have to specify the pattern stuff even though it doesn't matter. Urgh – Kyle Aug 13 '19 at 15:47
  • This works perfectly with Angular, although chrome start too early, the hot module reloading makes sure the page is automatically refreshed when the "ng serve" is ready – Ibrahim ben Salah Jan 25 '20 at 02:27
  • 2
    Has this changed recently? I feel like this _was_ working, but only for like a day for me, and now it's not working .... I posted my own question on https://stackoverflow.com/q/68446841/1877527 but since you're my baseline here I figured I'd comment :-) – Philip Kahn Jul 20 '21 at 16:31
  • 2
    Today's VSCode update seems to have broken this again. – marczellm Nov 05 '21 at 09:10
  • 2
    It's broken again, it used to work perfectly – Fabi0_Z Dec 17 '21 at 12:36
  • I had added `problemMatcher` as suggested above. But had missed to enable `isBackground`. So setting both of these fields worked for me. – nik Dec 30 '21 at 20:28
  • For me, VSCode triggers an error when the pre-launch task starts (there is an option to continue debugging). This seems to be caused by the `regexp: "."` pattern. If you use an empty string it works as others have described with no error message pop-up from VSCode. – BrutalSimplicity Feb 20 '22 at 06:41
  • The problemMatcher did the job for me on windows – Chen Peleg Aug 04 '22 at 06:31
18

Background / watching tasks

Some tools support running in the background while watching the file system for changes and then triggering an action when a file changes on disk. With Gulp such functionality is provided through the npm module gulp-watch. The TypeScript compiler tsc has built in support for this via the --watch command line option.

To provide feedback that a background task is active in VS Code and producing problem results, a problem matcher has to use additional information to detect these state changes in the output. Let's take the tsc compiler as an example. When the compiler is started in watch mode, it prints the following additional information to the console:

> tsc --watch
12:30:36 PM - Compilation complete. Watching for file changes.

When a file changes on disk which contains a problem, the following output appears:

12:32:35 PM - File change detected. Starting incremental compilation...
src/messages.ts(276,9): error TS2304: Cannot find name 'candidate'.
12:32:35 PM - Compilation complete. Watching for file changes.

Looking at the output shows the following pattern:

  • The compiler runs when File change detected. Starting incremental compilation... is printed to the console.
  • The compiler stops when Compilation complete. Watching for file changes. is printed to the console.
  • Between those two strings problems are reported.
  • The compiler also runs once the initial start (without printing File change detected. Starting incremental compilation... to the console).

To capture this information, a problem matcher can provide a background property.

For the tsc compiler, an appropriate background property looks like this:

"background": {
    "activeOnStart": true,
    "beginsPattern": "^\\s*\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? - File change detected\\. Starting incremental compilation\\.\\.\\.",
    "endsPattern": "^\\s*\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? - Compilation complete\\. Watching for file changes\\."
}

In addition to the background property on the problem matcher, the task itself has to be marked as isBackground so that the task keeps running in the background.

A full handcrafted tasks.json for a tsc task running in watch mode looks like this:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "watch",
            "command": "tsc",
            "args": ["--watch"],
            "isBackground": true,
            "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": "^\\s*\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? - File change detected\\. Starting incremental compilation\\.\\.\\.",
                    "endsPattern": "^\\s*\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM)? - Compilation complete\\. Watching for file changes\\."
                }
            }
        }
    ]
}

PS: Content taken from https://code.visualstudio.com/docs/editor/tasks

Edit-1

The task needs to be launched as a daemon then only isBackground is going to help. So you will have something like

"isShellCommand": true,
"command": "<absolute path to>/mga --config xyz abc &",
Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265
  • Unfortunately, `isBackground` doesn't help. vscode is still waiting for the prelaunch task to finish. – Mike Lischke Mar 01 '18 at 13:31
  • @MikeLischke, please check the edit and see if it helps – Tarun Lalwani Mar 01 '18 at 18:24
  • Stil no luck. After changing to what you recommended in your edit I get just error messages: `Failed to launch external program /mga --debugger config/main.json & . spawn /mga --debugger config/main.json & ENOENT`. Very weird. – Mike Lischke Mar 02 '18 at 09:50
  • Which OS are you using? – Tarun Lalwani Mar 02 '18 at 09:51
  • I'm on macOS. However, I'd need a solution that works on Linux, Windows and macOS. – Mike Lischke Mar 03 '18 at 09:20
  • I used this json and it had worked for me `{ "version": "2.0.0", "tasks": [ { "label": "sleep100", "type": "shell", "command": "echo sleeping for 100 && sleep 10 &", "isBackground": true } ] }` – Tarun Lalwani Mar 03 '18 at 09:29
  • I tried that too, only to get the error that the preLaunchTask cannot be tracked (whatever that means), after the 10 seconds. I used the exact content you wrote in your previous comment. The commands worked however in a terminal, so it must be a vscode problem. – Mike Lischke Mar 03 '18 at 18:35
  • Try this please `{ "version": "2.0.0", "tasks": [ { "label": "sleep100", "type": "shell", "command": "echo sleeping for 10 && sleep 20 &", "isBackground": false, "promptOnClose": false, } ] }` – Tarun Lalwani Mar 03 '18 at 18:55
  • Hmm, this seem indeed not to wait, but goes pretty far off the original idea. I want the task itself not to wait, not use some OS specific tooling to accomplish that (as it is not portable). – Mike Lischke Mar 04 '18 at 09:05
  • @MikeLischke, have you checked it on windows? I can't check on windows but Linux and MacOS it would work and I have checked VS Code source code, there doesn't seems to be any config that I could obviously see which would allow us to just launch and forget about the task – Tarun Lalwani Mar 05 '18 at 07:35
  • The Window command line doesn't support setting a task to backround with the trailing `&`. And somehow it really makes no sense to even use that. After all, vscode claims to have support for background tasks and even has special properties for that, but still fails without such a hack. – Mike Lischke Mar 05 '18 at 08:35
1

As of Nov 2022, the accepted and upvoted solutions to this question did not work.

I essentially needed a way to run Jacoco report after Junit tests finished running inside vscode java test runner. I managed to hack a way using bash and nohup, it may not be the solution for everybody but it works in my case.

tasks.json:

    "tasks": [
        {
            "label": "runJacocoReport",
            "type": "shell",
            "command": "./delayTheReport.sh"
        }
    ]

delayTheReport.sh

echo "Starting"
coproc nohup ./report.sh > nohupout.txt
sleep 1
echo "Report started in background"

report.sh

echo "Sleeping"
# This is magic number, you can replace it with a loop that checks for a certain file to exist or similar
sleep 15
echo "Starting"
# Do the thing you need to do
....
Simone Gianni
  • 11,426
  • 40
  • 49
1

I wanted to start a watch task after I launched firefox, and I ran into the same issue: my watch task blocked firefox from launching (or vice versa, if I switched the order). Since I kept on landing on this question whenever I googled for a solution, I want to share the way I solved my problem, because I think it'll help others:

Launch configurations have a concept called Compounds. Basically, it groups other launch configurations and they will start and run in parallel. In my case, that's all I needed. Here's the relevant documentation:


Compound launch configurations

An alternative way to start multiple debug sessions is by using a compound launch configuration. A compound launch configuration lists the names of two or more launch configurations that should be launched in parallel. Optionally a preLaunchTask can be specified that is run before the individual debug sessions are started. The boolean flag stopAll controls whether manually terminating one session will stop all of the compound sessions.

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Server",
      "program": "${workspaceFolder}/server.js"
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Client",
      "program": "${workspaceFolder}/client.js"
    }
  ],
  "compounds": [
    {
      "name": "Server/Client",
      "configurations": ["Server", "Client"],
      "preLaunchTask": "${defaultBuildTask}",
      "stopAll": true
    }
  ]
}

Compound launch configurations are displayed in the launch configuration dropdown menu.


I used this for my "compounds": { "configurations" } value: ["Launch Firefox", "npm run watch"],

Daniel Kaplan
  • 62,768
  • 50
  • 234
  • 356
0

July 2023. VSCODE Version: 1.81.0-insider (user setup) Worked for me (tasks.json):

    "problemMatcher": [
        {
          "pattern": [
            {
              "regexp": ".",
              "file": 1,
              "line": 1,
              "column": 1,
              "message": 1
            }
          ],
          "background": {
            "activeOnStart": true,
            "beginsPattern": { "regexp": "." },
            "endsPattern": { "regexp": "^.*$" } // <-- right here
          }
        }
      ]

So my explanation: I'm using "command"

Get-Content C:\\xampp\\php\\logs\\xdebug.log -Wait -Tail 10

Before Debug logs got cleaned up. So basically you need to find a pattern that will work for you. As "endsPattern": { "regexp": "^.*$" } basically means end signal whatever content it might be...