Can I set a C# preprocessor directive from a central file? - c#

I need to add some logging to my app, and it needs to be in release mode, and I need to make sure that the logging code isn't running in production. Therefore I'd like to use a #define and #if to make sure the log statements are removed when I move to production.
Trouble is, I need the logging in multiple files, and it's a pain to put a #define at the top of every file. Is there a way to have a centralized #define? That way I can remove the single #define rather than a #define from all files(which means I'll almost assuredly forget one).

On the command line, use the /define switch. In Visual Studio, choose the "Build" tab from the properties page for the project and fill in the "Conditional Compilation Symbols" section.
Consider also instead of using conditional compilation, to instead make your logging methods conditional methods. That's a more pleasant-looking alternative. That's how Debug.Assert works; it is a conditional method, so if the debug preprocessor symbol is not defined, the compiler simply removes all calls to the method before code generation.
See also my article on the subject:
http://ericlippert.com/2009/09/10/whats-the-difference-between-conditional-compilation-and-the-conditional-attribute/

Are you using Visual Studio? In the project Properties page, on the "Build" tab, there's a "Conditional compilation symbols" text box.

Yes, this is typically done in your build file, or the script you use which creates your build. You specify it as command-line arguments to MSBuild.

To add to Dave's answer, global conditional compilation symbols can also be specified in Visual.
Right-click on your project and go to Properties
Go to the Build tab
You can specify the symbols that you like (DEBUG is already turned on by default for Debug configurations, so this might actually give you what you want already) for the given configuration, or select "All Configurations" at the top to specify certain symbols for all configurations.

Call the logging everywhere you want.
Define the logging api entry methods with
[Conditional ("DEBUG")]
public void WriteDebugMessage(...)
Build your program in debug mode (which, by default, defines 'DEBUG' in VS). These calls will be part of your assembly.
Build your program in release mode (or - remove the DEBUG symbol from the build definition). These calls are now meaningless no-ops and won't run.
Seems like what you want?

Related

Removing the code with preprocessor in .net

I have .net C# application. In the application have two set of code for different client.
We were thinking of removing the part of code through preprocessor. Diabling the part with config file parameter is not an option for us.
We want simple setup like:
#define DEBUG
//....
#if DEBUG
Console.WriteLine("Debug version");
#endif
The only issue is, our part of code is distributed into multiple files and multiple projects in the solution.
So we want to define globally the preprocessor “DEBUG” at one place. Preferably in project property or something.
What is the best option for us?
Look for "Conditional Compilation Symbols" on the "Build" page of the project property dialog. You can set it per-build configuration.

Hiding code from a DLL while debugging

I've created a DLL with a Class Library Project with some classes. While adding this DLL as a reference in another projects and debugging, when going step by step or when the class returns an Exception the code from the class is shown.
How can I hide this? I want the exception to be shown on the class instruction, not inside and allowing to see al the code. And when debugging by steps, I want to do the methods without steping inside the code of the method.
Just like if you step through str.Split(), for example. You don't see the code and all the steps. You just see the error on that line or jumps to the next one.
For example:
Dim myObj As New myClass.SomeObj()
myObj.MyMethod()
I do not want the code inside MyMethod to be shown.
Add on the specified method a DebuggerStepThrough attribute to prevent step into. If an exception occures, the debugger breaks at the method call, not inside the method. See MSDN
The behavior you describe is a convenience. It allows the caller to see exactly what is going wrong by looking at the details of the code he's trying to consume. Microsoft even supports this for the .NET Framework source, and it's rather useful in my opinion. I'm not really sure why you'd want to disable it. You can always just use F10 (Step Over) instead of F11 (Step Into) when debugging so that the DLL's code remains available in case you ever need it.
But if you are sure that you don't want to be able to step into any code from the DLL, you need to make sure that the debug symbols are not available to the client application. Visual Studio generates these symbols in the form of a PDB file, which contains the location of the source files and mappings between the generated code and the source lines.
Contrary to some of the other answers, the generation of debug symbols is unrelated to whether the code is optimized (e.g., a "Release" build). I've written about this before in the context of why you might want symbols for an optimized build, but the point is that these are two orthogonal settings. You can turn on optimization and turn off symbol generation, and vice versa. Suffice it to say that I strongly recommend generating debug symbols for all builds.
You can disable the generation of debug symbols in the project's properties (it's hidden under the "Advanced..." button), or you can just move the PDB files to ensure that the client application cannot locate them when debugging. By default, a build places them into the same directory as the binary output, so that when you add a reference to the DLL, Visual Studio finds them easily. If you move either the symbols or the binaries, it won't be able to find them. (The debugger also searches the symbol path, but your symbols probably won't end up there.)

How to undefine the symbol CONTRACTS_FULL?

Visual Studio defines the CONTRACTS_FULL symbol automatically if
you enable contract checking in the Code Contracts tab of the Project
Properties page.
- C# 5.0 In a Nutshell (page 518)
I'd like to disable/undefine the symbol but it doesn't appear in the Conditional compilation symbols field of the Build tab in the project settings.
(I'm not interested in disabling code-contracts completely! by that I simply mean that setting the contract checking to None is not a solution).
If it matters, the reason I want to do this is because in my release builds I only want to throw on Contract.Requires<TException>, and I don't want to throw ContractException at all.
One "solution" I found is to put #undef CONTRACTS_FULL at the first line of each file, it fixed it but actually doing that would be horrible.
(BTW up until now VS didn't define CONTRACTS_FULL and I had to define it myself, but I guess some setting changed accidentally)
You cannot run the contract tools and undefine the CONTRACTS_FULL symbol. The tools depend on that being defined. Nothing will work if you try to force this. That is why we define the symbol automatically inside the msbuild scripts.
Users of the Code Contract tools should never manually try to define or undefine the CONTRACTS_FULL symbol as it is a tool controlled variable.
I've read that book, and there WAS a contract level that only used Contract.Requires. It was the option before none in there, but it's somewhere in that section in the book, definitely.
However, I can't help you with globally undefing CONTRACTS_FULL. Sorry. I think though that in that contract checking level it's automatically undef'd.
EDIT: Yeah, you need to put it at level one (ReleaseRequired).

Check using preprocessor if app is a winforms or asp.net

Is this possible to check in assembly what client (winforms app or asp.net page) is running it?
I want to add some methods but only for specific client.
I know, there is predefined DEBUG (#if DEBUG). Where can I find full list, what can I check using preprocessor?
To expand on m0sa's answer, preprocessor directives are basically just a string passed to the compiler.
If you are so inclined, you can add new build configurations (example: instead of Debug/AnyCPU and Release/AnyCPU, you could make WebDebug/AnyCPU, WinformsDebug/AnyCPU, WebRelease/AnyCPU, etc).
Then in the properties page of your project, for each configuration you could provide a value in the 'Conditional compilation symbols' field. For example, for WebDebug and WebRelease, you could provide the conditional symbol WEB. Then, you would be able to use:
#if WEB
using MyNamespace.WebStuff;
#endif
You will need multiple build configurations for that and define different a preprocessor directive for each one. You can set the conditional preprocessor directives in the Build tab of the project Properties page.There are no other directives defined, just the DEBUG directive which you can turn on and off (together with the TRACE directive) in the same tab. Note that DEBUG it is not defined for the "release" build configuration. This is kind of what you will need to do to enable different versions of the assembly to be built.
References:
MSDN
www.davidarno.org <-- see this one for a more visual description

How to set project wide #define in C#

I have several classes in a project which need to only be in certain builds of the application which are currently not ready for release or debug.
To prevent these classes from being used, I want to set around them this:
#if USE_MYCLASS
// Code here...
#endif
Unfortunately, I don't know how to setup a project-wide #define.
Is there functionality in Visual Studio to set project-wide definitions?
If there is, though I don't need it right now, is there a functionality to set solution-wide definitions?
If there is no functionality for such (seeing as C# does not have include files, I suppose it's possible), is there any method or plugin of doing this functionality without using the command line compiler and /D?
You can do that in the project properties, but not in source code.
Project Properties => Build => Conditional compilation symbols
You can specify whichever symbols you need (space delimited, but IIRC is is quite forgiving). Note that DEBUG and TRACE can also be toggled with a checkbox.
I have some projects with multiple "release" build configurations, with different symbols in each (for building 2.0 vs 3.0 vs 3.5 versions - see <DefineConstants> here)

Categories