3

I am running Windows 7 64-bit operating system on my development machine, using .Net 4.5 and MS Visual Studio 2012. I have several C# projects that use the System.Threading.Task namespace. I want to be able to build these projects on a server that all of our developers have access to. The problem is that that server is running Windows Server 2003, which does not support .Net 4.5, and the System.Threading.Task namespace does not exist in versions of .Net before 4.5.

I can set up new build configurations with a compile-time constant that I can check to determine which namespace to include, but before I do that, I'm wondering if there's already a pre-defined constant I can use. I doubt it, since as far as I know compile-time constants can only be defined or not defined in C#, unlike C++ in which they can have specific values.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
ROBERT RICHARDSON
  • 2,077
  • 4
  • 24
  • 57
  • 1
    Why not use the `Microsoft.Bcl` nuget package? https://www.nuget.org/packages/Microsoft.Bcl/ – Jon Skeet Jun 23 '14 at 20:24
  • 3
    Targeting 2 versions of framework with the same code is somewhat painful - have you considered to just target 4.0 (possibly with pre-4.5 versions of Task libraries that where release as futures or CTPs) OR upgrade server to 2012? – Alexei Levenkov Jun 23 '14 at 20:25
  • Was going to comment on Sav's answer. That is a runtime constant, but you could possibly use a powershell/build script to access the runtime constant, and then pass/define a compile flag/symbol to pass to the compile step. Probably more trouble than it is worth though to do it that way. – AaronLS Jun 23 '14 at 20:26
  • 2
    Consider changing title to something like "How to build a .NET 4.5 application on older server OS supporting older .NET?" – AaronLS Jun 23 '14 at 20:28
  • @AaronLS Agreed, this seems like a [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – dcastro Jun 23 '14 at 20:29

2 Answers2

2

First, the Task namespace (or rather, Tasks namespace) did exist in .NET 4.0, albeit with far more limited features (read: slightly fewer sugar methods) and no async/await keywords. Though more limited, this may help open up the possibility to simply setting the platform for your program to .NET 4.0, as that resolves a lot of your issues.

While you cannot use compile time constants (ie items marked by the const keyword) to exclude/include code, you can use symbol definition to do this via the #if directive. As long as you arrange your symbols properly, this can also be an effective way to separate compiled code, since &, |, and nested #ifs are all allowed and work as expected.

Regardless of included namespaces, however, a program built against .NET 4.5 is still going to run 4.5 and won't work on a machine that doesn't support it, even if all the features you use WERE available in 4.0. In addition, you can't change the .NET platform per build configuration, but you might be able to get away with making a mirror project that invokes the same files and folders, but instead builds against 4.0. All in all, I advise going 4.0 reading the following update and going Mono instead.

UPDATE: Another option might be to consider Mono as, according to their Download Page, the newest Mono maintains compatibility with Windows XP and Server 2003. I advise getting Xamarin as well so you can test run the code against the Mono platform, but note that Mono reads the same IL that .NET does, and Xamarin is designed to read/write the same project and solution formats as VS.

David
  • 10,458
  • 1
  • 28
  • 40
2

In c# you need to define the constants for os by yourself.

In the .csproj file do the following

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
    <IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
  </PropertyGroup>

  <PropertyGroup Condition="'$(IsWindows)'=='true'">
    <DefineConstants>_WINDOWS</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition="'$(IsLinux)'=='true'">
    <DefineConstants>_LINUX</DefineConstants>
  </PropertyGroup>
</Project>

After that in your .cs file, you can use constants like

        #if _LINUX
           Console.WriteLine("This is Linux");
        #elif _WINDOWS
           Console.WriteLine("This is Windows");
        #else
            Console.WriteLine("Unknown os!");
        #endif

You can check for OSX also similarly.

Renju Ashokan
  • 428
  • 6
  • 18