7

In my csharp code I need to define a constant where its value is set from environment variable expansion during compile time.

In this example let's talk about any arbitrary string, such as "Hello World".

For c++ there seem to be various approaches. See the following answer, for example: https://stackoverflow.com/a/22828929

Surprisingly I wasn't able to find a similar solution for csharp.
In particular, there seems to be no way to tweak the "*.csproj" file accordingly?

PS:
As mentioned in the answer by Hans Passant below: there is some logic for "DefineConstants", but they only give you some kind of boolean flag, so you can use it for conditional statements such as "#if TESTFOO" in your source code. you will not be able to use the actual value of the environment variable.

One possible "workaround" (to dynamically generate additional source files) is described in the following answer, for example: https://stackoverflow.com/a/4453285

But I'm still looking for an official solution that is more "straight".

paulgutten
  • 293
  • 3
  • 11
  • Related or duplicate: [Can I make a constant from a compile-time env variable in csharp?](https://stackoverflow.com/q/4450231/3744182). – dbc Jul 04 '20 at 20:07

2 Answers2

13

The C# build system does not support using environment variables strongly. Somewhat inevitable in C++ builds, its build model dates from the 1970s, but given a pass by Microsoft for C#. It does have a fantastic knack for causing build breaks when you try to rebuild your app a year or more after having finished the project. Or quickly when you try to build on another machine and its environment isn't set correctly. Having all the build config in one place is the superior solution.

But MSBuild supports them, you can refer to an environment variable with $(NAME) in the .csproj file. You can for example set a conditional compilation symbol with it, the kind you test in an #if expression. That requires editing the .csproj file by hand, use a text editor like Notepad. Locate the <DefineConstants> element, there are normally two. One for the Debug build and another for the Release build. A silly example:

   <DefineConstants>DEBUG;TRACE;$(USERNAME)</DefineConstants>

And used like:

    static void Main(string[] args) {
#if hpassant
        Console.WriteLine("It's mine!");
#endif
        Console.ReadLine();
    }

Oops, testing it a bit more reveals that it also works fine from the IDE :) Project + Properties, Build tab, Conditional compilation symbols = $(USERNAME). Nice.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Yes, you should have mentioned that. You'll need to look in another corner, write a little C# console app that generates a small .cs file that's part of your project and run it in a prebuild event. It is going to be brittle. – Hans Passant Mar 25 '15 at 14:44
  • Something to note: Once you put this in the csproj file or enter it from the IDE, the Conditional compilation symbols field will show the actual value of the environment variable when it is reloaded. It seems to keep it as the $() notation in the csproj, but it could be confusing to someone not understanding where the value came from and trying to modify it... – Steve In CO Apr 09 '20 at 03:21
0

C# does not support preprocessor macros. The only way to generate/modify source code before the compiler sees it (that is what you want to do) are template/macro expansion engines (like mustache or t4)

DrKoch
  • 9,556
  • 2
  • 34
  • 43