I have a new .Net application where I have made a WIX installer for. The WIX installer is a copy paste from other solutions where it is working without problems. It makes use of heat to automatically harvest the files needed. However, now I have run into a problem where it doesn't work for the current project. In the proj file where the heatdirectory is described, there is the following condition
Condition="'%(ProjectReference.ContentProject)'=='True'"
This condition works in the other solutions, however now it means that heat is not run when build.
I have googled, but I haven't been able to find out what ProjectReference.ContentProject means ?
Can anybody enlighten me, what it means and why it might not work in this solution ?
Thank you.
ContentProject only means something if you include it in your ProjectReference. See an example here.
<ItemGroup>
<ProjectReference Include="..\MyWCF.WcfService\MyWCF.WcfService.csproj">
<Name>MyWCF.WcfService</Name>
<Project>{8e528b38-2826-4793-a66d-f6ff181e1139}</Project>
<Private>True</Private>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
<ContentProject>True</ContentProject>
<DoNotHarvest>True</DoNotHarvest>
<PackageThisProject>True</PackageThisProject>
</ProjectReference>
</ItemGroup>
Related
I've been busy turning on code analysis for one of our solutions. On Friday everything was going well.
I had added the following to one of our csproj files:
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<CodeAnalysisRuleSet>ca.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.2" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2" />
</ItemGroup>
And spend some time on Friday working through the warnings, like this:
Disable all warnings in ca.ruleset
Enable one
Fix all instances
Re-build the solution to verify the fix
GOTO 2
This had been working really well. I came in this morning and picked up where I left off, except that when I got to step 4 (rebuilding the solution), I suddenly had 3k+ warnings from our unit test project.
I'm not sure why code analysis is now being applied to this other project and I can't seem to disable it.
Some observations:
The csproj file of the unit test project has no references to either FxCop or StyleCop.
Nor does it refer in any way to ruleset.ca
dotnet clean doesn't help
Checking out another branch (one without any CA turned on) stops analysis for both projects (as expected), but switching back results in them both being analysed again.
I'm using VS Code, so can't play around with any of the GUI settings that people seem (according to my Googling) to suggest for CA issues
My .sln file doesn't appear to have any reference to CA at all - it's just the usual project and build definitions.
I'm beginning to think this must be an issue with MSBuild.
Has anyone ever seen this before? What was the fix?
Update: Have filed a bug with the MSBuild team.
As per the bug report, this seems to be a general MSBuild thing and unrelated to any particular environment. For now I'm just going to add a blanket ignore ruleset, but it's hardly ideal.
Found a workaround via my bug report.
Nick Guerra suggested adding PrivateAssets="All" to the PackageReference statement in the csproj file of my main project.
In other words, for me, this:
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.2" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2" />
Became this:
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.2" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.0.2" PrivateAssets="All" />
A quick dotnet clean && dotnet build later, and all those warnings vanish!
It seems as though this attribute enforces what should already be the default behaviour: that analysers should be treated as being private to the project to which they are directly added. Relevant bug.
We had issues in our build with some of our dependencies forcing really old version of a library we were using ourselves at a newer version. This got slightly worse with transitioning towards the new style of project files that no longer explicitly mention DLL resources brought in by NuGet packages, because we lost the ability to mark such assemblies by aliases.
Now, I found out a solution of basically the same problem at NuGet's GitHub. I adapted it for our needs in the following way:
<Target Name="AliasLog4Net" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
<ItemGroup>
<ReferencePath Condition="'%(FileName)' == 'log4net'">
<Aliases>l4n</Aliases>
</ReferencePath>
</ItemGroup>
</Target>
It works magically. I want to know why though.
I can't find documentation for ReferencePath. Specifically, I would love to know what can I test for in the Condition attribute, apart from %(FileName)?
How can I log this logic? Is there a way to write something out for every ad-hoc application of the alias in this way?
With .net core (project.json) I used to switch between nuget packages and source code by adding the path to source code to the projects field in the global.json. After I did that it would add all the projects that it could find in that path that could replace the nuget packages I referenced.
I used this feature alot because I have my own nuget packages that I use, but I want to test the changes in my other project before I publish. But once I switched to Sdk 1.0.0/VS 2017/csproj .net core that feature seemed to disappear.
The alternative is just manually adding each project, switch the references manually (since they are broken up into project, nuget and sdk references), and then after switch it all back.
Any thoughts or advice would be great.
UPDATE:
Sounds like there is no equivalent in csproj (as expected), but there are msbuild workarounds for now (As of the initial VS 2017/.NET Core SDK 1.0.0 release)
Yes, I too had gotten used to this functionality and built my workflow around it. I am still looking for a solution but I'm currently playing with the idea of using conditional logic in the csproj files. Since it's now msbuild, you can do things like this:
<Choose>
<When Condition="Exists('..\..\..\MyProject')">
<ItemGroup>
<ProjectReference Include="..\..\..\MyProject\src\MyProject\MyProject.csproj" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<PackageReference Include="MyProject" Version="1.0.0" />
</ItemGroup>
</Otherwise>
</Choose>
This replaces the hard reference to a package with a conditional that uses a project reference if it can find the source code (in this case the directory), and a package reference if can't.
So by default you would be referencing the package, but if you want to debug one of your projects, you check it out in the location that the conditional checks, and add the project to your solution.
This way you only need to change your solution file (by adding the project) when you want to include source code, instead of rewiring all your project references.
For others that are interested in attempting to emulate with Global.json did, I worked around this for now using a couple powershell scripts and a custom json file that mimics it. Check out my answer here:
https://stackoverflow.com/a/43795974/5504245
An extension of this question, but slightly different, and the accepted answer does not quite work for this situation.
We've got a process in place on the build of our project which is generating some additional files, these files are getting (correctly) generated into the /bin folder as expected. However they are not getting copied across when this project is referenced as a dependency.
Following the above questions accepted answer (with a little bit of tweaking), I managed to get them copying across to the dependant project however they are all getting put into a /bin sub folder of the dependants /bin folder (i.e. /bin/bin), which is not what I need to have happen.
The process we're running is a 3rd party process (specifically Surviveplus.XmlCommentLocalization), so I have no control over that side of it.
I could do something additional on the dependant project to move them out of the /bin/bin into the level up, but I'd rather have the original project work as I'd expect it to.
This is the ItemGroup I'm using, derived from the other question:
<ItemGroup>
<Content Include="$(OutputPath)\**\*\*.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
I've also tried setting specifically the TargetPath value, which while un-documented (or I'm blind to it), seems to exist - as per the msbuild output log
<ItemGroup>
<Content Include="$(OutputPath)\**\*\*.xml" KeepMetadata="TargetPath">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>..\</TargetPath>
</Content>
</ItemGroup>
But it appears that when it comes to the Copy task it just ignores it, and resolves a new TargetPath. I've also tried a myriad of combinations of attributes/item types in that item group (i.e. None, EmbeddedResource) but they didn't solve it either.
Ideally I suppose MSBuild needs to mark the generated files as part of the generated assembly? But after getting lost in .target files and MSDN docs, I couldn't figure it out.
MSBuild being used is version 12.0, compiling for .net4.5.
Is there a way I can suppress .codeanalysislog.xml and .lastcodeanalysisuccceeded from getting dropped in my output directory on build?
I agree, the bin folder is bad place for these FxCop files. However suppressing these files from getting generated, or deleting them unconditionally after the build is not the best decision. First, removing .lastcodeanalysissucceededd will cause code analysis re-run even when nothing has changed. Second, removing .CodeAnalysisLog.xml will make it almost impossible to investigate details of analysis errors and warnings. So you might as well just turn off the code analysis for the project.
Instead, let me suggest another solution. It solves the problem with those pesky files in your bin folder, while preserving all functionality of FxCop. The solution is simply put those files somewhere else. The best place is obj folder, i.e. $(IntermediateOutputPath).
Paste this section in your project file after all <import>'s, at the end of the file:
<PropertyGroup>
<CodeAnalysisLogFile>$(IntermediateOutputPath)$(TargetFileName).CodeAnalysisLog.xml</CodeAnalysisLogFile>
<CodeAnalysisSucceededFile>$(IntermediateOutputPath)$(TargetFileName).lastcodeanalysissucceeded</CodeAnalysisSucceededFile>
</PropertyGroup>
Never mind, I put in a post-build target to delete these files
<Target Name="AfterBuild" AfterTargets="Build">
<ItemGroup>
<FilesToDelete Include="\**\*.CodeAnalysisLog.xml" />
<FilesToDelete Include="\**\*.lastcodeanalysissucceeded" />
</ItemGroup>