ROBERT RICHARDSON
ROBERT RICHARDSON

Reputation: 2279

Check the operating system at compile time?

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.

Upvotes: 5

Views: 2203

Answers (2)

Renju Ashokan
Renju Ashokan

Reputation: 514

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.

Upvotes: 3

David
David

Reputation: 10708

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.

Upvotes: 2

Related Questions