How to define compilation symbols only when profiling? - c#

I'd like to define a compilation symbol like PROFILE only when I'm profiling a C# project in Visual Studio. In a normal debug or release build it should not be defined.
So the code between #if and #endif gets only compiled when profiling.
#if PROFILE
DataCollection.StartProfile(ProfileLevel.Process, DataCollection.CurrentId);
#endif
It should be a compile time check, no runtime check. The reason is that some of our team have no profiler on their PCs (not included in VS 2012 Standard) and we would like the code to compile on any system without changes.

Create a new configuration:
Click Build then select Configuration Manager.
Click Active solution configuration and select New.
Type Profile in Name and select which configuration will be used as template (for profiling I guess Release).
Confirm with OK, it'll create new configurations named Profile for each project in your solution.
Open properties of each project, and in the Build tab add PROFILE symbol in Conditional compilation symbols then save properties.
Now when you build the Profile configuration the PROFILE symbol will be defined. I suggest you take a look to this post too, if you automate your builds you may keep your PROFILE symbol out of the solution using MSBuild properties via command-line (I suppose you do not build for profiling very often).
EDIT
With configuration you can do that but it won't save you from a broken reference to Microsoft.VisualStudio.Profiler.dll). What I suggest is to move all this code to another library that you'll ship to them compiled. There you'll expose just a method:
public static class ProfilingHelpers
{
[Conditional("PROFILE")]
public static void StartProfiling()
{
DataCollection.StartProfile(ProfileLevel.Process, DataCollection.CurrentId);
}
}
In your code you'll always call it but it'll be executed only when PROFILE is defined (so you won't need to add a new configuration to each project but to one DLL only).

Related

How to share major and minor version of the main application with its DLLs?

I have a large WinForms application (C# , .NET 4.5.2) with several own DLLs (plug-ins for the application), all as different Projects in the same Solution. I use Visual Studio 2015 Community.
The main app and all the DLLs have their version number assigned in their respective AssemblyInfo.cs files like this:
[assembly: AssemblyVersion("1.0.*")]
Now I want to up the version of the application to, say, 2.0.. I also want all the DLLs to be 2.0.. The way I currently have it I would need to go into each DLL and manually change the version to 2.0.*.
Is there a way to inherit the "2.0" part from the application so that, in future, I would only have to change major and minor version number in one place?
I did some searching but was not able to find the answer.
Update:
What I was hoping is that I can replace
[assembly: AssemblyVersion("1.0.*")]
with something like:
[assembly: AssemblyVersion(some_string + ".*")]
where "some_string" is a string containing the major and minor version number. But I wouldn't know where I can define that string, or if this is possible at all.
Add a link to the original AssemblyInfo.cs file to the other project via the project solution explorer:
Right click on the project -> Add -> Existing item -> Add as link (from the dropdown menu)
Now, once you change the original AssemblyInfo.cs, any changes will be applied to all the projects to which the file was added as a link.
Edit:
To avoid duplicating attributes that should be unique per assembly (such as the GUID), make two files, one for the shared attributes like version number, and another for assembly specific attributes. No one forces you to put everything into the same file. It does not even have to be named AssemblyInfo.cs
In Visual Studio of you can set Pre build events.
Right click the project and select properties
Go to Build Events
then in the first box for pre-build event you can launch a simple script like this
if $(ConfigurationName) == Release C:\AssemblyChanger.exe $(ProjectDir)
This sample script above will Launch "AssemblyChanger.exe" located on your c drive and it will pass the current Visual Studio project folder as an argument. from there it is very simple to read the Assembly.cs on the specific project that manage the "version" and edit the one in the path that was pass as argument. Plus this will only be called if you are in Release mode (that "if" can be removed without a problem).
You can create a simple console application to do that.
That script can be set in all DLL pre build event so when they compile they call the script and they will get their assembly edited before the compiler create the DLL.

Is there a way to conditonally #define a symbol in a dependency?

I am working in a solution where there is a specific library in the solution that turns on or off functionality via #ifdef's.
I have another project in the solution that uses it as a dependency. In my build settings, I want to be able to define the symbols in the dependent library based on build configuration in my project. I cannot find any way to do this within Visual Studio.
Is there any way to accomplish this?
(I realize the ideal solution here would be to change those #ifdef's to something else, but please assume that I cannot edit code in the other project)
Build tab in project options depends on selected value of build configuration dropdown. You can test, when you've selected Debug, Define DEBUG constant is checked, but not in Release mode.
Just choose appropriate configuration (Debug, Release or custom one) and set value of conditional compilation symbols.
I don't think you can do that. There are no "solution level" defines, all defines are scoped to a project.
As #archil points out you may be able to achieve some by selecting correct configuration for the project.
One more option could be to build project with MSBuild directly instead of using normal VS IDE route, this way you will be able to override defines via command line (http://stackoverflow.com/questions/479979/msbuild-defining-conditional-compilation-symbols)

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

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?

VS2008: Multiple build configs with defines don't work as expected

I have a base library to maintain in multiple versions. I do a SVN switch whenever I need to work on another version.
I don't have multiple versions of my test application solution, so I thought that for different versions I could do multiple solution / project configurations that define symbols for the version to be able to have version-specific code in my test.
Currently I have the following build configurations in the test application solution: Debug, Release, DebugV10, ReleaseV10, DebugV15, ReleaseV15. In the *V10 and *V15 configs, I created and selected corresponding *V10 and *V15 PROJECT configurations for the two projects that have version-specific test code (not for all projects, most run normal Debug / Release configuration in the solution -Vx configuration).
In those project configurations I entered the corresponding conditional compilation symbols (VERSION10 and VERSION15).
Now in my code in the project I go like
#if VERSION10
// do v1.0 stuff
#elif VERSION15
// do v1.5 stuff
#else
// do trunk stuff
#endif
But apparently VS doesn't recognize the symbols. Even a simple #if DEBUG does not work anymore, allthoug define DERBUG constant is checked in all Debug* project configurations.
Is this a known thing? What can I do about it?
The concept that you describe sounds fine.
That is, the code uses:
#if VERSION10 ... #endif
and the Project configuration defines VERSION10
and a Solution configuration is set up that is set to use the above Project configuration.
As long as these are all set up correctly, I'd expect it to work.
The fact that you say even #if DEBUG isn't working as expected suggests that something is very broken.
I'd suggest you try the simplest possible case, to ensure you undersatand how to set it up: Create a new minimal "hello world" application that just has simple code that allows you to tell apart the versions:
#if VERSION1
Console.WriteLine("Hello from version 1");
#else
Console.WriteLine("Hello from version 2");
#endif
Then create project configurations ("Debug Version 1", "Debug version 2") and see if you can set them up (one with VERSION1 defined, one without) to get the two outputs when built.
Then add Solution configurations that use the above Project configurations, and build them to check that they print the right things when executed.
Once you've done this you should have a working system (an understanding of how these elements relate to each other) that you can apply back to your more complex project. To apply them back, I suggest deleting most of the project/solution configurations and then rebuilding them from scratch now that you are sure you know what to do - often rebuilding these things from first principles works out better than trying to tweak an existing 'broken' setup back into life.
Conditional compilation in C# is different from C and C++. See here for info on the ConditionalAttribute class.
For example:
doDebugOutput(); // unconditionally call the optional code
Conditional["DEBUG"]
void DoDebugOutput()
{
// do expensive debug-only output here
}

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