I am hacking around a problem we've created for ourselves. What I would like to do is log a warning in our TFS builds for any code that is instantiating a specific class. I don't want a run time warning (I've got one in place already), I want a build time warning that ProjectX is using BadClass.cs. The idea being it will give us an additional place to see things that need to be fixed once our hack is no longer needed.
So something like this:
public class BadClass
{}
public class OkClass
{}
public class MyBadService
{
var a = new BadClass(); <-- Logs a warning to the build output
}
public class MyOkService
{
var a = new OkClass(); <-- Does not log a warning
}
Edit:
I do not like the idea of using Obsolete; its a misnomer. We've already got code with Obsolete attributes and this would get lost in the noise. I don't want a generic warning that I can't control the message for. I want bright neon signs with klaxons firing and a thousand exclamation points in the message. Basically everything I can do short of failing the build. I'm using the #warning precompiler directive right now and its mostly doing what I want but it requires a human to remember to add the warning. I'm looking for something more automagic. I've seen third party libraries do stuff like this so I know its possible.
Why not just use the Obsolete attribute? It can generate a build warning for you:
https://learn.microsoft.com/en-us/dotnet/api/system.obsoleteattribute?view=netframework-4.8
You can even make it emit an error too if you want.
The answer could be negative I think.
It seems that you use or call msbuild.exe to build your C# projects. But as far as I know, MSBuild in fact calls csc.exe to build C# projects in build time.
So actually what you want is logging a warning when the compiler compile the C# code if it recognize somewhere in your code uses the BadClass in build time.
If you have the source code of BadClass in the same solution, add a project reference format to the xx.csproj which contains BadClass, and set a #warning in the BadClass it may generate the warning in build time.
But I think the scenario you're in is something like: You developed one Assembly and distribute it to your user, so you want it generates a warning when the user calls one BadClass in your assembly and builds his own project to remind him of taking care when using this bad class. If so, this is impossible for msbuild AFAIK. If I misunderstand anything, feel free to know me know :)
Update:
As Daniel and Johnson said, ObsoleteAttribute is enough to do this. Though no valid way to generate warnings from msbuild aspect directly, but msbuild will call C# compiler during build process, so generates a compiler warning can output to build output window.
Related
When compiling a solution with many projects, if I make a compile time error in a project that many other projects use I'll get a flood of errors in the Error List window of visual studio:
Error 80 Metadata file
'C:\trunk\Projects\Libraries\K2DataBaseClient\bin\x64\Debug\CEPCortex.dll'
could not be found C:\trunk\Projects\TradeAiTeacher\CSC
These errors indicate that a project couldn't be built due to another project not being built. These types of errors cascade and don't really tell me anything useful as I know that its all due to a core project failing to build.
These errors often make it harder to find the actual error in the window.
Is there a way to tell visual studio to suppress this type of output and just show me the compile errors in cases like this to make it easy to find what actual code is broken?
Ideally it once the compile error has been fixed we can toggle this hiding off so I see all errors.
I had originally left this version agnostic but visual-studio 2013 is the version I am most concerned with.
No. The C# compiler categorically refuses to consider one error more "important" than another one. It cannot know how important an error can be, it doesn't know enough about the reason it had to produce the error. A missing reference assembly can produce a lot of errors because type definitions are missing. Of course the compiler cannot know the difference between them being undefined because of the missing assembly reference (ignore) or you mistyping a name (don't ignore).
Interpreting the Error List requires a massively parallel computing machine that's capable of high-speed correlation inference and pattern matching. With practical quantum computing still a distant future, you need to use the one that's readily available to any programmer, the one you have between your ears. Start at the top of the list. And work your way down, feeling less inclined to fix them as you progress down the list.
Never hesitate to rebuild before getting to the end of the list when you fixed a gross error. Like a missing assembly reference.
I've found the best way to work with existing the visual studio behavior is to use the advice in this link: and make the compiler stop after the first compile error.
This seems to get as close to solving my problem as you currently can.
I'm currently dealing with a part-time (and annoying) bug with some extension methods in VB .NET (VS 2010 and VS 2008).
I have some client projects that use some extension methods from a "Framework" Project I created for general purpose.
However, sometime, when a try to start the solution, I get a long list of error saying the extension method "is not a member of" target object.
When this happen, I can rebuild the solution without getting any error but if I start the project again, the same error will be raised again.
So far I have 2 workaround
A) Go on the extension method definition, delete the tag, compile (with error), put the tag back.
B) Close Visual Studio et re-open it.
Is there any betterway to handle this problem?
There is an active bug report for this problem at Connect. There's a dire need for a repro, a project with specific steps to let them reproduce the issue in-house. Perhaps you can help, it's what it will take to solve it or recommend a workaround.
EDIT: one late addition to this answer, since I've posted this there have been additional questions that note a problem with the IntelliSense parser behaving different from the compiler. There's an issue with the multi-targeting feature, particularly in VS2010, triggered by the Client Profile option for .NET 4. It is the default for a new project. What goes wrong is adding an assembly reference that requires the full profile, commonly because of a dependency on System.Web. You'll get a warning for that, but that's quickly blown away with a large number of errors. The fix is to change the project's Framework Target from client to full.
I've recently encountered this same issue. My project would Build just fine but if I tried to use the Rebuilt option I would get the error about my extension methods not being found on the objects they were extending.
I have managed to fix this today by including an Import at the top of the classes using the Extension method.
So at the top of the file I actually have
Imports project_name.extension_module
I have no idea why this is required but it fixes the problem in my case. I hope this helps somebody else that has wasted as much time with this as I have!
Liam
A less time consuming work around than the two you listed is to "Rebuild Solution" instead of the normal Build Solution. This has always worked for me whenever I run into this problem.
We have something very similar. Call extensions merhod that extends type A. type is actually an instance of type B that implements interface C. interface C has a method with the same name as extension method.
Interface C declares method Foo
Class B inherits from A implements C
Static Class
Static method Foo (this A)
If A is C
(A as C).Foo
When debugging on the line if A is C it actually calls Foo multiple times and you can step at assembly level and see it indicates it is doing the comparison. The way we demonstrate that the call is happen Foo executes a sql statement and we can see sql profiler executing the code in Foo.
Change A as C to reflection and bug goes away. Or use debugger hidden/step through and bug is masked. Also if you micro-step the sql profiler shows the query is getting called multiple times (before Foo is actually called) for each assembly statement.
I'm working on a (rather horrible) project that involves importing a C++ class hierarchy through a dll interface. One of the more horrible details requires me know the 'decorated' names for the various class elements that are exposed - mostly member functions and static data.
There are many ways to achieve this - the assembly listing or map file, dumpbin, a dependency walker, the _FUNCDNAME_ macro, etc. Unfortunately, they all require me to actually compile the code or have the compiled dll - and all I have available is the header files. (That may leave you scratching your head for a minute - just take my word that it truly is a horrible project.)
Now, I can easily concoct something compilable from just the headers and use one of the above approaches. But if I can avoid it, that would be much better. So my question is: is there a way to browse decorated symbol names from within Visual Studio, a la Object Browser? I know that the decoration is technically done at compile time, but Intellisense does so many other things while you type that I'm hoping it might do this too.
If all else fail take that .h, rename it to .cpp, replace all semicolons (;) with
{
#pragma message(__FUNCDNAME__)
}
edit it a little, and compile it. You'll get your list.
I recently added a new project to my Visual Studio 2008 solution. Now, as I make edits in the new project, I receive a ton (~50) of type checking errors - indicating that an assembly reference may be missing. However, when I actually build the solution, the errors go away. As best I can tell, my dependencies are set and the build order is correct. What could be wrong?
It doesn't prevent me from building and deploying, but it's a major nuisance. It makes it hard to tell when I actually have introduced new errors (until I do compile). Thus, it erodes the usefulness of having the error window do static analysis.
Example, one of the 50 errors is this:
"The type of namespace name 'PersonManager' does not exist in the namespace 'Gideon' (are you missing an assembly reference?"
In reference to this line of code:
Gideon.PersonManager pm = new Gideon.PersonManager()
PersonManager is underlined in both places, and when I right click the type and selected 'find all references' I get an alert box that says "Cannot navigate to PersonManager"
However, the references are definitely there, because when I build, it works.
One other detail is that there is a mixture of C# and VB.net code, though I don't think that should make a difference.
Well, yes, the IntelliSense parser is not an exact replica of the C# compiler. It has a very different job to do, it needs to do something meaningful while the code is utterly broken since you are editing it. Tough assignment, they did a tremendous job with it. But as a side-effect, it can fail to parse things that are actually legal. It's quite rare but not unheard of, seen it myself a few times.
This won't go anywhere concrete until you at least give us some idea of what kind of errors you are seeing, along with a snippet of the code that generates them. You didn't do so, I can only recommend that you select another window so you don't have to look at them.
I had the same problem. I had a project in my solution that was causing the problem - I removed the project from the solution, then added a reference to that project in the main solution and the errors went away. Strange that it only happened on 1 machine. Opening the solution on another machine was fine...
Is there a "call stack" for compiler errors in Visual Studio 2005 (C++)?
For example, I am using a boost::scoped_ptr as the value in a QHash. This is however causing the following compile error:
1>c:\qt\include\qtcore\../../src/corelib/tools/qhash.h(743) : error C2248: 'boost::scoped_ptr<T>::operator =' : cannot access private member declared in class 'boost::scoped_ptr<T>'
From the build output I know which of my source files is causing the error and the line number in the qhash.h that is causing the error but I am trying to track down the line number in my source file that is generating the error (hence the "call stack" idea).
Please note, I am not looking for the solution to the problem of using a scoped_ptr in a QHash but the problem of tracking down where compile errors are generated. This would also be useful for helping track down weird warnings. More often than not I run into this problem when using templated classes.
Thanks!
Sometimes with strange errors it helps to preprocess the file and look at that output. With VS look for "Generate Preprocessed File" under preprocessor settings (or set the /P switch). This will generate XXX.i from XXX.cpp which may help you figure out the problem.
Make sure you turn off the switch after, with this option turned on it won't generate an obj file.
If you look at the build output, you should see which project and which .cpp file was being compiled when this error occurred.
There is really no notion of "call stack" here, because the compiler processes one source file at a time. You have a compiler error in the header file, so you need to find out which source file including that header was being compiled.
These types of errors can be hard to track down. Usually I end up comment out code and finding the offending line and working from there. After doing it a while you will learn to better read the error messages and understand what tripped up the compiler. As it stands the compilers error messages are just horrible.
In this case it is saying that you have an object of type boost::scoped_ptr<T> that it is trying to copy but the class won't let you (operator= and the copy ctor are both hidden). So you need to look at how the class is used and see why it is trying to copy it. Maybe a scoped_ptr isn't what you need. Maybe you need a shared_ptr?