For a Visual C++ project (no CLR support) I created a simple custom .targets file and added it to the project through the "Build Customization" dialog.
The custom target simply takes all files within a specific folder (say "Configuration") and copies them to a folder with the same name in the output directory.
Thereby MSBuild should do an incremental build, i.e. it should only copy the files if they have been changed.
If I run MSBuild from the console for the project the incremental build works correctly. If I run it inside Visual Studio I always get the message that the project is up to date, even if I changed my custom files.
I found an answer by looking into the book "Inside the Microsoft Build Engine, Second Edition".
On page 280 they actually saying that the IDE does a "fast up-to-date check" on the project-level. It only spawns a project build and does a more fine-grained check on the individual tasks if this rough project-level check fails.
I expected that Visual Studio simply hosts MSBuild, i.e. you use the IDE to edit your .proj files and when you build them Visual Studio just invokes MSBuild to do the up-to-date check for all build targets. I think this way it would be much clearer.
I got a workaround by following the suggestions here, but it is not a really satisfying solution since I always have to add all the files to the project and set the Custum Build Tool property which is easy to forget: