21

In order to define my environment variables in a single place a configured a task in which a run a shell script. The task is run as preLaunchTask in my launch.json.

In my launch.json I now try to reference the environment variables I configured in the script (like export AWS_REGION="eu-west-1").

The launch.json looks as follows:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch",
            //..
            "env": {
                //"AWS_REGION": "us-east-1",        //works
                "AWS_REGION": "${env:AWS_REGION}",  //doesn't work, why?
            },
            "args": [],
            "preLaunchTask": "setupEnv",
        }
    ] }

4 Answers 4

19
  • Doesn't work, why?

According to this post from user weinand...

The ".env" file is read and processed after VS Code has substituted variables in the launch config. So your debugged program will indeed see the environment variable "FOO" with the correct value but VS Code's variable substitution in the launch.json will not see it.

The reason for this is that ".env" files are a node.js concept and not a generic platform mechanism. So VS Code does not know anything about .env files, but the node.js debugger knows about .env files.

... this functionality in launch.json is specific for applications running on Node.js, although that's not what M$ explains in their documentations for VSCode.

  • Possible solution

For Python applications (possibly for other platforms as well) environment variables defined in a .env file (or whatever name you like) will be available for your application as long as the following configuration is present in launch.json...

{
    "version": "0.2.0",
    "configurations": [
        {
            [...]
            "envFile": "${workspaceFolder}/.env", // Path to the ".env" file.
            [...]
        }
    ]
}

Note that just exporting a variable...

export SOMEVAR_A=1234

... will not make the environment variable SOMEVAR_A available for the application being executed by the VSCode debugger nor for the settings - especially inside "env" and "args" ("configurations") - in launch.json as, for example, in this case...

{
    "version": "0.2.0",
    "configurations": [
        {
            [...]
            "env": {
                "SOMEVAR_A": "${env:SOMEVAR_A}"
            },
            "args": [
                "${env:SOMEVAR_A}"
            ]
            [...]
        }
    ]
}

NOTE: In our tests the ${env:SOMEVAR_A} syntax did not work in any scenario. That is, didn't work for the application ("env") and didn't work for the settings ("args") in launch.json.


PLUS I: Dirt Hack

For values present in "args" ("configurations") you can use the hack below...

{
    "version": "0.2.0",
    "configurations": [
        {
            [...]
            "envFile": "${workspaceFolder}/.env",
            "args": [
                "`source \"${workspaceFolder}/.env\";echo ${SOMEVAR_A}`"
            ]
            [...]
        }
    ]
}

... as the configuration in "envFile" doesn't work.

Notice, although, that the following construction...

[...]
"args": [
    "`echo ${SOMEVAR_A}`"
]
[...]

... would also work for "args" as long as the environment variable "SOMEVAR_A" has been previously exported in the conventional way.

The same reasoning would work for a tasks (tasks.json), but in both cases we can't guarantee that.


TIP: An .env File Example

SOMEVAR_A="abcd"
SOMEVAR_B="efgh"
SOMEVAR_C=123456

PLUS II: Export Variables

There are cases where you will need to export variables (eg. export SOMEVAR_A="abcd") so that they can be consumed by certain resources. In these cases there may be problems, because the fact that we export variables prevents (we don't know why) that they are seen in the context of the "envFile" configuration "envFile": "${workspaceFolder}/.env".

A workaround to get around these limitations is to add set -a before the variables set and set +a after it. With this we were able to meet the two scenarios as this example...

#!/usr/bin/env bash

set -a    
SOMEVAR_A="abcd"
SOMEVAR_B="efgh"
SOMEVAR_C=123456
set +a

... or in a more compatible and safe way use set -a/set +a as in this example...

[...]
"args": [
    "`set -a;source \"${workspaceFolder}/.env\";set +a;echo ${SOMEVAR_A}`"
[...]

VSCode's support for environment variables is a mess!


  • Conclusion

We don't know if the limitations we are dealing with here are from VSCode's own design or are bugs. Anyway, it doesn't seem to make much sense.

These procedures were tested on Manjaro Linux (Arch based).

[Ref(s).: https://unix.stackexchange.com/a/79077/61742 , https://stackoverflow.com/a/30969768/3223785 ]

1
  • 6
    UPDATE: After the last VSCode update, none of the hacks/workarounds presented in this thread are possible anymore. Thank you M$ for making our life even more complicated and not coming up with any other solutions. 🙄 Commented May 24, 2022 at 19:19
3

Looking at the issue comment quoted below, it seems this is currently not possible.

${env:...} only expands environment variables that were set in the parent shell that ran code. It doesn't expand variables set in the tasks.json env options.

https://github.com/Microsoft/vscode/issues/47985#issuecomment-460678885

1

It doesn't work as Eduardo Lucio stated. Here is some alternative that works at least on my case that sometimes uses env.sh file to load the environment variables and require .env file for VsCode debugging in Go project. To launch the application normally, load the env using commmand $ source env.sh. On this case, you want to load .env file instead.

Env-Example: Linux/WSL2

  1. If the .sh is what I tought of, probably just some line of export commands: env.sh
export DBUrl="sql-connection-string-here"
export DBPass="somedbpass"
  1. Create the prelaunch task to generate the .env file .vscode/tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "buildenv",
            "command": "sed",
            "args": ["s/export //g", "local_env.sh", ">", ".env"],
            "type": "shell"
        }
    ]
}

you can see that it calls sed to replace any export with empty string and rewrites a .env file.

  1. On .vscode/launch.json, load the preLaunchTask and change the target envFile to the generated file:
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "My App Debug",
            "type": "go",
            "request": "launch",
            "mode": "debug",
            "program": "${workspaceFolder}",
            "preLaunchTask": "buildenv",
            "envFile": "${workspaceFolder}/.env",
        }
    ]
}

Now, everytime VsCode run the debugger, it generates .env file and only need to maintain single env.sh file.

Reference: https://stackoverflow.com/a/38746951/12325366

0

Use the vmArgs option to pass a Java property to the VM (i.e. -Dname=value), e.g.:

{
    ...
    "configurations":
    [
        {
            "type": "java",
            "name": "MyApp",
            "request": "launch",
            "mainClass": "org.example.MyApp",
            "projectName": "my-app",
            "vmArgs":
            [
                "-Dname=value"
            ]
        }
    ]
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.