问题
I need to let all projects in solution contain some additional build actions, e.g. StyleCop validation, autogenaration of AssemblyInfo's, etc.
My idea is to make some kind of solution-wide prebuild event that will check all project files for containing nodes that match specific xPath. It's not a hard part, it can be solved either with custom build task, or with some third-party Xml handling task. I didn't investigate it deeply yet, but it definitely won't make a problem worth mentioning here.
The questions are how to
1) extend solution file with some custom tasks? It shouldn't be necessary integral part of solution. It is desired, but can be omitted while building from VS, it will be enough to have some specific command line that executes it.
2) if its not possible, there is option described in "Solution-wide pre-build event?". It's hacky, but if there is no other options, I'll use it. But how to get list of project files from solution file? Please, take into account that folder that contains solution may contain extra project files that shouldn't be check, so just enumerate all ***.*proj is not an option.
P.S. Any other options for entire problem are welcome too :)
回答1:
You can create any custom tasks with any conditions using built in MSBuild feature to extend functionality: CustomAfterMicrosoftCommonTargets, CustomBeforeMicrosoftCommonTargets.
See my example. You can add custom tasks in your .targets file for every step in build process. You can add conditions to turn on/off those actions and so on. It doesn't rely on sln file, but you can have tasks that will be VS-specific with condition '$(BuildingInsideVisualStudio)'=='true'. You can call them from command line - you need to specify the name of target with key /t:MyCustomTarget.
Sideeffects: if your custom target willn't have any specific conditions - it will be called in every similar project.
回答2:
There's a much simpler way of handling this sort of thing. Instead of trying to dynamically change project file contents, you can use a shared build .targets files that are imported into your Visual Studio projects via the mechanism described at http://msdn.microsoft.com/en-us/library/ms171464.aspx (with another example at http://msdn.microsoft.com/en-us/library/ms171464.aspx).
回答3:
I've never approached this problem from the solution level - you don't have a lot of control when calling msbuild against a solution file.
Instead, I've typically approached this by having each project in the solution import another msbuild file that contains all the common targets. This gives you a lot of fine-grained control over what each project will do, since you were mentioning that each project in the solution does not need to do all the extra tasks.
<Import Project="_pathToCommonTargets_" />
After importing the common targets, you can control what happens with hooks into the build project - i.e. overridable targets that occur at specific points when "Build" is called on that project. Additionally, you can create new targets in the common targets file that you can just call instead of the build target, for when you're building outside of Visual Studio.
<Target Name="AfterBuild" >
<!-- Other tasks here -->
<!-- Calling a common target -->
<CallTarget Target="_commonTargetName_" />
</Target>
Also, I wouldn't recommend using something like XPath to determine what nodes are in each project file. It would be much cleaner to use the functionalities incorporated in msbuild. For example, you can check whether properties are set (children of propertyGroup nodes) and perform operations against collections (children of itemGroup nodes.)
- Msbuild homepage: http://msdn.microsoft.com/en-us/library/0k6kkbsd.aspx
- Msbuild overridable custom targets: http://msdn.microsoft.com/en-us/library/aa337604.aspx
来源:https://stackoverflow.com/questions/5715435/how-to-check-all-projects-in-solution-for-some-criteria