When attaching to a program using cppdbg with processId as ${command:pickProcess}, the command pick does not wait for the preLaunchTask initialization/finalization, processId command pick should start just after the preLaunchTask finalization.
Please refer to this issue: https://github.com/microsoft/vscode-cpptools/issues/5287
Good observation: launch config resolution and variable substitution should only take place after the preLaunchTask has finished.
@gustavomassa I acknolwedge the behavior you have hit. However we were always behaving like that, we can change as you suggest to first run the preLaunchTask and only then resolve. This could potentialy break extensions that rely on filling in the preLaunchTask attribute as part of the resovleDebugConfigurations call. I am not sure if there are extensions like this, but there could be.
I have just checked our docs and our API spec and as far as I saw we do not specify what should be run first.
Since there are still two weeks unitl the end of endgame I am fine with changing the behavior to first run the preLaunchTask. Hopefully that should give us enough time to catch any potential breakages.
I just tested this and we can not change it, since some preLaunchTask depend on variables to be resolved before it is run.
For example, our starter Typescript extensions has the following launch configuration:
And because preLaunchTask is ${defaultBuildTask} that requires that we first resolve variables and only then run the prelaunch task. Due to this, I am pushing this issue to On-Deck and I am open for suggestions
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"preLaunchTask": "${defaultBuildTask}"
}
Thank you @isidorn for investigating this!
From what you describe, there are two different needs:
Given that the order in which these are executed is arbitrary, a potential solution would be to propose another equivalent to preLaunchTask that would be called before resolveDebugConfiguration.
So, we would have an order of execution like:
preResolveTask (name TBD)resolveDebugConfigurationpreLaunchTaskIs this a possibility that could be considered?
@daniv-msft yes that is one option. Though please note that we already have a postDebugTask that runs after debugging, so what you are suggesting is to introduce a third task. While it is a possiblity I would first like to try to find a smaller scoped solution.
But is it possible that your extension simply handles this on it's own?
As part of the resolveDebugConfiguration you can use the Task api to run any task you want?
@isidorn Thank you for your reply. I prototyped what you suggested, and running the task directly from the resolveDebugConfiguration seems to be working.
However, that implies recreating the equivalent of the preLaunchTask logic manually, which is not great:
public async resolveDebugConfigurationAsync(debugConfiguration: vscode.DebugConfiguration): Promise<vscode.DebugConfiguration> {
const targetTaskName = debugConfiguration[`preLaunchTask`];
const availableTasks: vscode.Task[] = await vscode.tasks.fetchTasks();
const targetTask = availableTasks.find(t => t.name === targetTaskName);
const taskExecution = await vscode.tasks.executeTask(targetTask);
await new Promise((resolve, reject): void => {
vscode.tasks.onDidEndTask((e: vscode.TaskEndEvent) => {
if (e.execution.task.name === taskExecution.task.name) {
resolve();
}
});
});
// Code that relies on the task being executed here.
...
// TODO: Find a way so that the preLaunchTask don't get executed another time when resolveDebugConfiguration completes.
}
Also, I'm not sure how sustainable it is on the long run. Typically, if in two months a timeout is added by VS Code on resolveDebugConfiguration to limit the maximum time spent before returning (as it was added for the task provider API), this solution wouldn't work anymore. The task we run takes around 20 seconds to complete, and waits for a user interaction, so we would be very sensitive to any timeout added.
Looking again at the Typescript example you provide, I'm wondering if we could find a solution by resolving variables (such as ${defaultBuildTask}) before running preLaunchTask, but only calling the resolveDebugConfiguration function after that.
That way, we would fix the scenario I'm presenting without breaking Typescript. Would this be possible?
@daniv-msft great to hear that the workaround is working for you.
Yes the suggestion which you said that we only first resolve variables but do not call resolveDebugConfiguration has crossed my mind, however that might break some other corner case.
However I am open for experimenting with that change and am also open for a PR which tackles this.
@daniv-msft @isidorn
Please note that there are two resolveDebugConfiguration hooks: one before variables have been substituted, one (resolveDebugConfigurationWithSubstitutedVariables) after the substitution took place.
If I understand the current logic correctly the preLaunchTask is run after both hooks.
Would it help (and would it be possible) to run the preLaunchTask after the first hook but before the second?
@weinand yes I guess we could also change it such that we run resolveDebugConfiguartion then run the prelaunchTask and then run the resolveDebugConfigurationWithSubstitutedVariables. However I am not sure if this would cover @daniv-msft use case.
... and we would not run the second hook if preLaunchTask fails.
@isidorn, @weinand > Thank you for your replies. Yes, that solution would work for me!
Since that might potentialy break some clients I am assigning this to August so we do this change at the start of the August milestone so we have enough time to gather feedback.
Thanks @isidorn, that sounds indeed reasonable.
As we agreed upon I have pushed a change such that prelaunchTask is ran before the resolveDebugConfigurationWithSubstitutedVariables
I have verified that this does not break the starter TS ext sample.
@daniv-msft it would be great if you try your use case and let us know if it works for you. VS Code insiders with this change should be out on Friday.
Thanks @isidorn, that's great! I'll give this a try once the VS Code insiders release is available, and I will let you know how it goes.
@isidorn I just wanted to confirm that I've been able to update our code according to the latest version of insiders, and I can confirm that the fix you pushed works for us.
Thank you again for your help fixing our scenario!
@isidorn I wonder whether regressions like #105179 are triggered by this change...
@weinand might be. Let's wait for the C++ team to investigate https://github.com/microsoft/vscode/issues/105179 and let us know
fyi @wardengnaw and @gregg-miskelly for C#. Gist of the above discussion is in this comment
I can't think of any reason why this change would be a problem for C#. @WardenGnaw do you have the cycles to see what is going on with #105179?
The issue is "Build and Debug Active File" is a TextEditorCommand (C_Cpp.BuildAndDebugActiveFile) and it uses a ConfigurationProvider to find configurations to display to the user. The user selects a configuration and then the command launches the debugger with the selected configuration.
@isidorn @weinand Do we need to write the configuration selected to a launch.json before calling vscode.debug.startDebugging?
_Adding C++ Language Server Folks:_
@sean-mcmanus who worked on the feature
@elahehrashedi who orignally reported this issue
@WardenGnaw no, you do not need to write configurations into launch.json before calling startDebugging. You can just pass the full configuration into the startDebugging API and it should just work.
Actually, it might be the Attempt to use the user's (possibly) modified configuration before using the generated one.
If that call throws an exception, we call startDebugging with the full configuration.
Did VS Code add a feature to show an error dialog when it could not find a matching name launch configuration?
@WardenGnaw not that I can remember.
If you could write a simple starter extension that shows this problem that would be great.
@isidorn This is not a regression for 1.49.0 since this also appears in 1.48.1. It is due to trying to use vscode.debug.startDebugging with a configuration that does not exist in launch.json.

@sean-mcmanus We should validate if that configuration exists in launch.json instead of calling vscode.debug.startDebugging and using the thrown exception to detect if we should launch via configuration.
Thanks for trying it in older versions, that always helps.
Based on @daniv-msft comment adding verified label.
Most helpful comment
Good observation: launch config resolution and variable substitution should only take place after the preLaunchTask has finished.