In my web.config I have:
<system.diagnostics>
<switches>
<add name="logLevelSwitch" value="1" />
</switches>
</system.diagnostics>
Is there a way that I could call, for example:
System.Diagnostics.TraceSwitch["logLevelSwitch"]to get the current value?
Once you've defined the switch value in your web.config file, it's easy to get this value from your application by creating a TraceSwitch with the same name:
private static TraceSwitch logSwitch = new TraceSwitch("logLevelSwitch",
"This is your logLevelSwitch in the config file");
public static void Main(string[] args)
{
// you can get its properties value then:
Console.WriteLine("Trace switch {0} is configured as {1}",
logSwitch.DisplayName,
logSwitch.Level.ToString());
// and you can use it like this:
if (logSwitch.TraceError)
Trace.WriteLine("This is an error");
// or like this also:
Trace.WriteLineIf(logSwitch.TraceWarning, "This is a warning");
}
Moreover, for this to work, according to the documentation:
You must enable tracing or debugging to use a switch. The following
syntax is compiler specific. If you use compilers other than C# or
Visual Basic, refer to the documentation for your compiler.
To enabledebugging in C#, add the /d:DEBUG flag to the compiler command line
when you compile your code, or you can add #define DEBUG to the top of
your file. In Visual Basic, add the /d:DEBUG=True flag to the compiler
command line.
To enable tracing using in C#, add the /d:TRACE flag to
the compiler command line when you compile your code, or add #define TRACE to the top of your file. In Visual Basic, add the /d:TRACE=True
flag to the compiler command line.
Related
I have a C++ DLL which has #defines used like (these defines are automatically defined based on the build configuration, e.g. Debug, Release, etc)
#if defined(CONSTANT)
..
// Some code
#else
// Some other code
I need same functionality in C# dll.
Is it ok if I define some global constants in C# dll and use them
instead of defines?
e.g.
if(Globals.SomeConstant == SOMEVALUE)
// Do this
else
// Do smth else
Then when I want to ship the DLL I will in advance (probably as a default value during declaration) assign SOMEVALUE to Globals.SomeConstant - will this work this way? (Depending on which configuration I need).
I saw some similar questions but they weren't about DLLs.
You can use it similarly as in c++
You can define / undefine them in your source code or as a conditional compilation symbol. In visual studio this can be done using Solution Explorer - Properties - Build - conditional compilation symbols
However, nowadays people tend to use a configuration file for these constants. This way, you don't have to recompile your source code nor redistribute it to change the behaviour.
The most easy method is via visual studio solution explorer - properties - settings
You can add settings for most types. Booleans come closest to #define. Using an int can give you more than two possibilities. See the difficulties if you wanted to be able to use several values for a TimeSpan or an URI using #define.
The nice thing about using the settings is that a class is generated for you to easily access the settings.
Another method is to read the config file directly using the System.Configuration.ConfigurationManager class. This gives you more freedom about the format of the configuration. The disadvantage is that you have to convert the read values into proper types yourself, inclusive handling errors if the value can't be read.
Summarized: advantages of the config file method:
No need to change source files
No need to recompile
No need to re-install
only change the config file on those machines that need the change
improved type safety
My previous answer lead to a more questions than it answered. Hence I thought an example would help.
Suppose I have a DLL, called MyDll. It has a configuration setting that in really old times would have been defined using #define.
My C-synctax is a bit rusty, but it would look like:
#define UseAlternateGreeting
public class MyClass
{
public string GetGreeting()
{
#if defined UseAlternateGreeting
return "Hello World!";
#else
return "Here I am!";
#endif
}
}
Now suppose we have several programs that use this DLL. Program! wants to use the default setting. However Program2 wants to use the alternate setting. There is no way to solve this.
Besides if we want to change the value of the setting we have to recompile and redistribute everything to everyone.
Wouldn't it be easier if we could just edit a file with notepad to change the string?
Luckily Microsoft also saw the advantage of this. Over more than 10 years we have the idea of configuration files. Assemblies have a config file with the name of the application and the extension config. This file can easily be edited using any text editor by those who know what the configuration items mean.
If we replace the #define with an item in the config file the greeting could be changed to the alternate greeting without having to recompile and redistribute the whole program.
Luckily Visual Studio helps us a lot when creating the config file.
Preparations
Let Visual Studio Create a console application in a new Solution: name the program ConfigExample
Add a new Library to this application, name it MyDll
View the properties of MyDll
Add a Setting.
Name: MySetting,
Type: string,
Scope: application,
Value: Hello World! (without string quotes)
In project MyDll create a class MyClass
public class MyClass
{
public string GetText()
{
return Properties.Settings.Default.MySetting;
}
}
Go to project ConfigExample
Project Add reference to MyDll (via tab page solution)
Use the code in your main:
using MyDll;
static void Main(string[] args)
{
var obj = new MyClass();
var txt = obj.GetText();
Console.WriteLine(txt);
}
Compile and run, and you'll see the proper text displayed. If you go to the debug / bin directory of the program you'll find a text file ConfigExample.config. Open it in a text editor and you'll see... nothing abut hello world!
This means that your program is not really interested in a special setting, the setting that was default the time that MyDll was built may be used.
However, if you want to use a special setting,
In visual Studio, Go to project MyDll
open file app.config
a.o. you'll find the following
(to prevent the editor interfering with the formatting, I added an apostrophe to each line)
'</configSections>
'<applicationSettings>
'<MyDll.Properties.Settings>
'<setting name="MySetting" serializeAs="String">
'<value>Hello World!</value>
'</setting>
'</MyDll.Properties.Settings>
'</applicationSettings>
Copy paste this part to ConfigExample.Config
for all already distributed programs do this in the folder where the executable is (in your case: debug/bin)
for all ConfigExample programs that will be built in the future do this in visual studio in App.Config of the ConfigExample project.
The result will be as follows:
'<?xml version="1.0" encoding="utf-8" ?>
'<configuration>
' <configSections>
' <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="MyDll.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
' </sectionGroup>
' </configSections>
' <applicationSettings>
' <MyDll.Properties.Settings>
' <setting name="MySetting" serializeAs="String">
' <value>Hello World!</value>
' </setting>
' </MyDll.Properties.Settings>
' </applicationSettings>
'
' <startup>
' <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
' </startup>
'</configuration>
Now all we have to do is change the Hello World into an alternat greeting
' <MyDll.Properties.Settings>
' <setting name="MySetting" serializeAs="String">
' <value>Here I am!</value>
' </setting>
' </MyDll.Properties.Settings>
Run the program without building it and you'll see that the new value is used.
Advantages:
- It works with a lot of types that can be assigned from string - Type.IsAssignableFrom(typeof(string)). Visual Studio already supports a lot of types including TimeSpan and DateTime.
- You don't have to recompile your source code to change the value
- Several executables can use their own configuration setting: one program could use the original greeting, the other can use the alternate one
- If your program doesn't provide a value in the config file the default value is used.
- You don't have to read the configuration yourself.
- It is type safe: if you say it is a TimeSpan, then you have to do some serious typing to confuse it with for example an integer.
Well there is a lot more to be said about configuration, you can even have a configuration per user. But that's far outside your question about alternatives for plain C #define
I'm currently using CloudConfigurationManager.GetSetting("setting") to get settings for my application, but it's writing logs of everything it's checking to the console (in both Debug and Release):
Getting "setting" from ServiceRuntime: FAIL.
Getting "setting" from ConfigurationManager: PASS (Data Source=...
Getting "setting" from ServiceRuntime: FAIL.
Getting "setting" from ConfigurationManager: PASS (Data Source=...
Is there any way to prevent it from doing this, or an alternative version that's less verbose?
Mostly I just like my unit test output to be nice and clean, but I'm also a little concerned that it's printing out things like connection strings (and hence passwords) in plain text on the production server.
CloudConfigurationManager.GetSetting now has a method overload with a parameter called outputResultsToTrace.
If you pass false to this method, then it'll disable the Trace.WriteLine used elsewhere to "spam" the Trace log.
So
var mySetting = CloudConfigurationManager.GetSetting("MySetting");
becomes
var mySetting = CloudConfigurationManager.GetSetting("MySetting", false);
I found this by looking directly at the source code on GitHub: https://github.com/Azure/azure-sdk-for-net/blob/52fc67253a176bea01c37c164f71c7eba8eaedba/src/Common/Configuration/CloudConfigurationManager.cs#L35
It's probably worth mentioning that this overload is not documented: https://msdn.microsoft.com/en-us/library/azure/mt634648.aspx
So I'm not sure if it's an official and supported part of the API, or if it's something that might change or go away in the future.
This change was made at the end of 2015: https://github.com/Azure/azure-sdk-for-net/commit/e14398136d7d3b6d5e4675f1e8ccbdd37a8c6b01
Not really. If you look at the code of the underlying GetValue method you'll see this:
private static string GetValue(string providerName, string settingName, Func<string, string> getValue)
{
string str1 = getValue(settingName);
string str2;
if (str1 != null)
str2 = string.Format((IFormatProvider) CultureInfo.InvariantCulture, "PASS ({0})", new object[1]
{
(object) str1
});
else
str2 = "FAIL";
Trace.WriteLine(string.Format((IFormatProvider) CultureInfo.InvariantCulture, "Getting \"{0}\" from {1}: {2}.", (object) settingName, (object) providerName, (object) str2));
return str1;
}
The Trace.WriteLine is always called without taking into account Debug or Release. Now you can simply remove the Default listener which should suppress all messages:
<system.diagnostics>
<trace>
<listeners>
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
Now if you look at the CloudConfigurationManager it doesn't do that much. If this is a problem for you you can cook up something yourself, starting with this:
if (RoleEnvironment.IsAvailable)
return RoleEnvironment.GetConfigurationSettingValue(setting);
else
return ConfigurationManager.AppSettings[setting];
Note: The CloudConfigurationManager does a lot more than this, like loading the assembly without assembly reference.
Alternative option, if you're calling CloudConfigurationManager.GetSetting() in one part (ie, a wrapper/helper class):
var oldListeners = Trace.Listeners.Cast<TraceListener>().ToArray();
Trace.Listeners.Clear();
var stringValue = CloudConfigurationManager.GetSetting(key);
Trace.Listeners.AddRange(oldListeners);
First, we remove all listeners on Trace. Then we grab the setting, and re-add the listeners. Of course, this potentially could cause problems with threaded applications
I just installed the nuget package Microsoft.WindowsAzure.ConfigurationManager version 3.1.0, and I can confirm that the issue has been fixed in this version. Taking a look at the github issue referenced in the question's comments, we can see, in the changelog, the fetched value is no longer written to the trace output. In particular, the trace message has been changed from:
message = string.Format(CultureInfo.InvariantCulture, "PASS ({0})", value);
to:
message = "PASS";
This still makes the configuration manager quite verbose though.
We just ran into this ourselves...so very frustrating.
We can't remove the default listener because we are logging our own stuff on it.
There is an easy workaround though. Just use the good old fashioned ConfigurationManager.AppSettings["Microsoft.ServiceBus.ConnectionString"] and you will get the info you need without the annoying logging.
Hope that helps,
David
I had quite similar problems. I updated from Azure SDK 2.0 to 2.2 - during this process I used the NuGet Manager to update the Microsoft.WindowsAzure.Storage to the latest. The PackageManager automatically took Microsoft.WindowsAzure.Configuration to 1.8.0.0. I was not able to get this running (it was for .Net 2.0!?). After I manually set all References to
Microsoft.WindowsAzure.Storage 2.1.0.0
Microsoft.WindowsAzure.Configuration 2.0.0.0
everything worked.
I think this is because of the way CloudConfigurationManager.GetSetting loads the assembly and calls the funktions (via reflection).
Fixed in version 3.0.0. Please update Microsoft Azure Configuration Manager nuget package.
There are two separate issues here:
Setting values are logged in plain text (a security concern)
Messages are logged every time a setting is retrieved (a verbosity concern)
As others have noted, #1 has been fixed in a more recent version of the plugin.
Based on my experience (and some of the other responses here), #2 is still a huge annoyance.
Looking at WADLogsTable in Visual Studio's Queue Editor, note that the message level is 5 (i.e. verbose, according to this list of ETW levels).
Going off of the diagnostic config file schema, my approach to solving issue #2 was to limit the minimum severity level (e.g. warning, informational, verbose) of generic tracing to "information" (or more severe) and just ensure my own logging did not use the "verbose" level.
Here is the change I made in diagnostics.wadcfgx:
Original:
<Logs scheduledTransferPeriod="PT1M" scheduledTransferLogLevelFilter="Verbose" />
Fixed:
<Logs scheduledTransferPeriod="PT1M" scheduledTransferLogLevelFilter="Information" />
I have a Netduino and it is currently outputting accelerometer data to the System. Diagnostics.Debug window. I am waiting on a USB->232 converter in the mail to properly get the data from the device into my app via a serial port but I was wondering just for quick testing purposes if anyone knows if it is possible to read the data from the Debug window back into my app?
EDIT - Solution:
I am posting this here for anyone who want my solution. I originally thought that Nuf's answer worked "Data written to System.Diagnostics.Debug can be captured with TraceListener class. MSDN has short tutorial how to set it up." but I found out that the Listener can only get data from within it's own application. Since I was using a Netduino, the Debug output was from a different program which meant the trace listener could not read it. So I found a way to read the text in the Output box directly.
Base on code from MSDN:
You will need to 3 references to your project. They are located in the .Net reference tab - EnvDTE, EnvDTE80, and extensibility.
using EnvDTE80;
using EnvDTE;
using Extensibility;
public static string ReadDebugBox()
{
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.10.0");
string data = "";
OutputWindow ow = dte.ToolWindows.OutputWindow;
OutputWindowPane owP;
TextDocument owPTxtDoc;
EditPoint2 strtPt;
owP = ow.OutputWindowPanes.Item("Debug");
owP.Activate();
owPTxtDoc = owP.TextDocument;
strtPt = (EditPoint2)owPTxtDoc.StartPoint.CreateEditPoint();
return strtPt.GetText(owPTxtDoc.EndPoint);
}
public static void ClearDebugBox()
{
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.10.0");
OutputWindow ow = dte.ToolWindows.OutputWindow;
OutputWindowPane owP;
TextDocument owPTxtDoc;
EditPoint2 strtPt;
owP = ow.OutputWindowPanes.Item("Debug");
owP.Activate();
owP.Clear();
}
There may be better ways of doing it but this is just one that worked for me so i thought I would share it.
Data written to System.Diagnostics.Debug can be captured with TraceListener class. MSDN has short tutorial how to set it up.
There are two ways to set this up, one way is to declaratively set this up in your app.config file. There's a lot of advantages to doing this such as not needing to recompile your application when changes are needed.
<configuration>
<system.diagnostics>
<trace autoflush="false" indentsize="4">
<listeners>
<add name="configConsoleListener"
type="System.Diagnostics.ConsoleTraceListener" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
Alternatively, you can also do this inside of your code to output Debug traces to your application's console window.
Debug.Listeners.Add(new ConsoleTraceListener());
I'm using StyleCop and want to suppress some warning which does not suit my style. I prefer to have solution for
1) in-line code suppressing
2) global setting suppressing
I've searched the internet but still not sure how to do the suppressing.
For method 1), They said to add the lines:
[assembly: SuppressMessage("Microsoft.Design",
"SA1202:All private methods must be placed after all public methods",
Scope = "namespace", Target = "Consus.Client.ClientVaultModule.Services.OnlineDetection")]
But they do not say where and which namespace to be used.
For method 2), they said to use GlobalSuppress file but it seems not easy to search for a how-to do it at the moment.
Please help.
[Edited]
In my case, I have the warning about SA1202: All private methods must be placed after all public methods which is bothering since I group my related codes into regions. I want to suppress those warning for just some certain methods.
Here's what you need:
[SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess")]
An example of inline suppression would be similar to this - examine the namespaces in the code compared to the suppression
namespace Soapi
{
///<summary>
///</summary>
///<param name = "message"></param>
///<param name = "statusCode"></param>
///<param name = "innerException"></param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)")]
public ApiException(string message, ErrorCode statusCode, Exception innerException)
: base(String.Format("{0}\r\nStatusCode:{1}", message, statusCode), innerException)
{
this.statusCode = statusCode;
}
A global supression file is a file in the root of your project named GlobalSuppressions.cs and might look like this:
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
//
// To add a suppression to this file, right-click the message in the
// Error List, point to "Suppress Message(s)", and click
// "In Project Suppression File".
// You do not need to add suppressions to this file manually.
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Soapi.ApiException.#.ctor(System.String,Soapi.ErrorCode,System.String,System.Exception)")]
And you can generate this code automatically by right-clicking on the warning.
Starting with StyleCop 4.3.2, it is possible to suppress the reporting of rule violations by adding suppression attributes within the source code.
Rule Suppressions
http://stylecop.soyuz5.com/Suppressions.html
but it says -
Global Suppressions
StyleCop does not support the notion of global suppressions or
file-level suppressions. Suppressions must be placed on a code
element.
If you've installed StyleCop, you can right-click your project and there will be a StyleCop option. Click this and you'll see you can prevent certain rules from even running against your project. Moreover, you can create a separate rules file to share between different projects. This means you can configure the rules once the way you want them and then share that configuration between all your projects.
For individual overrides, SuppressMessage is the way to go.
Go to Solution Explorer
Go to your project
Expand references
Expand Analyzers
Expand StyleCop.Analyzers
Right click on a particular rule which you want to disable at a global (project) level
Set Rule Set severity -> Select None
Read the admonition from Style Cop, looking for the alphanumeric code. In your case 'SA1202'. Then browse to the corresponding page on the Style Cop website. Change the URL as appropriate https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1202.md
Copy the line labelled 'How to Suppress Violations'. Paste the attribute above the class about which Style Cop moans
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Reviewed.")]
Cant you just remove the rule instead of soiling your code?
Same goes for FxCop...
1.
In your case, correct SuppressMessage attribute should like like the following:
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess")]
private void SomeMethod()
{
}
Note that you can place it on any other element (e.g, on the class - then all similar violations in the entire class will be supressed).
I also agree that it's quite unobvious what to write in these fields.
Actually, the first one should be the fully qualified name of StyleCop analyser class and could be found from the source code (e.g. from here).
The second one should start with rule code, then colon and the name of the rule enumeration (luckily, it always looks like the rule name displayed in the Settings Editor, but with no whitespaces).
2.
Regarding suppressing rules "globally" - why don't just turn them off via Settings Editor? Settings files are inherited through the file system, so you could easily have one "main" settings file at the "top" of your folder structure, and some other files (holding the "difference" from main) with exceptions made for some projects, if you want so (like described here).
Good luck!
You can disable the rules you don't want in Settings.StyleCop file, which is in the project root folder.
You will need the namespace that contains the rule, which can be found here:
http://stylecop.soyuz5.com/StyleCop%20Rules.html
Settings.stylecop file code for your reference:
<StyleCopSettings Version="105">
<Analyzers>
<Analyzer AnalyzerId="StyleCop.CSharp.LayoutRules">
<Rules>
<Rule Name="ElementsMustBeSeparatedByBlankLine">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules>
<AnalyzerSettings />
</Analyzer>
</Analyzers>
</StyleCopSettings>
Alternatively you could move the code in regions into partial classes. Then the issue with the stylecop rule will go away.
In addition to the helpful answers already in place:
If you suppress a warning in the suppression file GlobalSuppressions.cs,
you can edit that [assembly: SuppressMessage(StyleCop...blabla line and entirely remove the Scope=... and Target=... tags. That makes the suppression global in the project.
The README.md for the StyleCop.Analyzers NuGet package used by Visual Studio 2015+ contains a link to the documentation for the rules. The documentation for each rule contains a "How to suppress violations" section. For the SA1202 rule, the options are:
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Reviewed.")]
and
#pragma warning disable SA1202 // ElementsMustBeOrderedByAccess
#pragma warning restore SA1202 // ElementsMustBeOrderedByAccess
Does anyone know how to get the current build configuration $(Configuration) in C# code?
If you unload your project (in the right click menu) and add this just before the </Project> tag it will save out a file that has your configuration in it. You could then read that back in for use in your code.
<Target Name="BeforeBuild">
<WriteLinesToFile File="$(OutputPath)\env.config"
Lines="$(Configuration)" Overwrite="true">
</WriteLinesToFile>
</Target>
There is AssemblyConfigurationAttribute in .NET. You can use it in order to get name of build configuration
var assemblyConfigurationAttribute = typeof(CLASS_NAME).Assembly.GetCustomAttribute<AssemblyConfigurationAttribute>();
var buildConfigurationName = assemblyConfigurationAttribute?.Configuration;
Update
Egors answer to this question ( here in this answer list) is the correct answer.
You can't, not really.
What you can do is define some "Conditional Compilation Symbols", if you look at the "Build" page of you project settings, you can set these there, so you can write #if statements to test them.
A DEBUG symbol is automatically injected (by default, this can be switched off) for debug builds.
So you can write code like this
#if DEBUG
RunMyDEBUGRoutine();
#else
RunMyRELEASERoutine();
#endif
However, don't do this unless you've good reason. An application that works with different behavior between debug and release builds is no good to anyone.
Conditional Compilation Symbols can by used to achieve this. You can define custom symbols the Properties > Build settings pane for each project, and the use the #if directives to test them in the code.
Example showing how the define the symbol UNOEURO and how to use it in code.
bool isUnoeuro = false;
#if UNOEURO
isUnoeuro = true;
#endif
Install the SlowCheetah Visual Studio extension.
Right-click on your config file and select 'Add Transform'.
Notice a transform for each build configuration.
Place a "Build" appSetting into the root config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<appSettings>
<add key="Build" value="" />
</appSettings>
</configuration>
And place a "Build" directive in each transform:
<?xml version="1.0" encoding="utf-8"?>
<!--For more information on using transformations see the web.config examples at http://go.microsoft.com/fwlink/?LinkId=214134. -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="Build" value="Debug" xdt:Transform="Replace" xdt:Locator="Match(key)"/>
</appSettings>
</configuration>
Then obtain the "Build" appSetting value in your C# code:
ConfigurationManager.AppSettings["Build"]
Please be mindful that you will not see the transforms when you are debugging: https://stackoverflow.com/a/17336009/109941
You can use a common static method with Conditional Attribute to set the flag to detect DEBUG or RELEASE mode. The SetDebugMode method will be called only when running in the DEBUG mode otherwise it is ignored by Runtime.
public static class AppCompilationConfiguration
{
private static bool debugMode;
private static bool IsDebugMode()
{
SetDebugMode();
return debugMode;
}
//This method will be loaded only in the case of DEBUG mode.
//In RELEASE mode, all the calls to this method will be ignored by runtime.
[Conditional("DEBUG")]
private static void SetDebugMode()
{
debugMode = true;
}
public static string CompilationMode => IsDebugMode() ? "DEBUG" : "RELEASE";
}
You can call it in the code like below
Console.WriteLine(AppCompilationConfiguration.CompilationMode);
I don't believe you can inject that at compile time into the assembly but one way you could achieve it would be to use MSBuild and add it to the config file of the application.
See this blog post about how to do multi-environment config files using MSBuild - http://adeneys.wordpress.com/2009/04/17/multi-environment-config/
Alternatively you could write an MSBuild task which would edit a certain compiled file (your C# or VB file) and have that run in the BeforeBuild task. It'd be rather tricky as you'd need to work out where to inject it into the file, but provided you had some kind of tokenization set up you should be able to do it. I also doubt it would be pretty!