I am having an issue trying to implement compiler-based code analysis in my C# .NetFramework solution. I decided to use Microsoft.CodeAnalysis.NetAnalyzers nuget package with some custom .editorconfig ruleset that I do not want to keep directly in the consuming project. I created another nuget with the .editorconfig and the idea is to copy the file to each consuming project before it is built in order to trigger the analysis (during build).
I tried an approach (described here) where the .editorconfig is copied to csproj location in a beforeBuild task defined in .props file
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="('$(Configuration)' == 'Debug')">
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
</PropertyGroup>
<ItemGroup>
<EditorConfigFilesToCopy Include="$(MSBuildThisFileDirectory)..\content\.editorconfig" />
</ItemGroup>
<Target Name="CopyEditorConfig" BeforeTargets="BeforeBuild">
<Message Text="Copying the .editorconfig file from '#(EditorConfigFilesToCopy)' to '$(MSBuildProjectDirectory)'"></Message>
<Copy
SourceFiles="#(EditorConfigFilesToCopy)"
DestinationFolder="$(MSBuildProjectDirectory)"
SkipUnchangedFiles="true"
UseHardlinksIfPossible="false" />
</Target>
</Project>
Unfortunately, the file seems to be copied too late as the msbuild ignores it during the build itself and does not fail due to CA violations as I would expect. If the file had been copied manually before running msbuild, it works.
Do You have any idea why it is like that and how to handle this issue properly?
Related
We have a nuget package we developed and use internally. One package has addtional unmanaged DLL's that need to be deployed. In VS2015, I right-click on the web application project and publish to a test server. None of the unmanaged DLL's in the package were published, but they are in the bin folder on my machine.
Here's what I'm trying in the package targets file:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="ExtraFilesPublishTarget">
<Message Text="########### NUGET DEPLOY ###########"/>
<ItemGroup>
<DistFiles Include="$(MSBuildThisFileDirectory)..\lib\dist\**\*.*"/>
<FilesForPackagingFromProject Include="%(DistFiles.Identity)">
<DestinationRelativePath>\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
<Target Name="DistBuildTarget" AfterTargets="Build">
<ItemGroup>
<DistFiles Include="$(MSBuildThisFileDirectory)..\lib\dist\**\*.*"/>
</ItemGroup>
<Microsoft.Build.Tasks.Copy SourceFiles="#(DistFiles)" DestinationFiles="#(DistFiles->'$(OutputPath)\%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
<PropertyGroup>
<copyallfilestosinglefolderforpackagedependson>
ExtraFilesPublishTarget;
$(copyallfilestosinglefolderforpackagedependson);
</copyallfilestosinglefolderforpackagedependson>
<copyallfilestosinglefolderformsdeploydependson>
ExtraFilesPublishTarget;
$(copyallfilestosinglefolderforpackagedependson);
</copyallfilestosinglefolderformsdeploydependson>
</PropertyGroup>
</Project>
When I publish, I see the NUGET DEPLOY message, but the next line in the output window is "Target "ExtraFilesPublishTarget" skipped. Previously built successfully."
The link above (http://blog.mjjames.co.uk/2012/10/deploying-non-project-files-with-web.html) solved my problems.
I did have another issue with targets not found. To save time in testing, I would edit my .targets file in the packages folder for my solution. If you add or rename a target in the local .targets file, VS2015 won't find the change since it caches the target names. You have to close down VS or reinstall the package to it to be found. You can change the elements within the target, you just can't change the name of the target or add a target.
I have an ASP.NET project that is included in multiple solutions. In each solution I'd like a different unreferenced project to be included in the ASP.NET project's build output. The solutions look like this:
Foo.sln
WebApp.csproj
Foo.csproj
Bar.sln
WebApp.csproj
Bar.csproj
Ideally, this would work even when debugging with F5. I tried doing this with build configurations, but deviating from the typical 'Debug' and 'Release' seems brittle when working within Visual Studio. Is there a typical way of doing this?
Disclaimer: I don't think this is a very good idea to do but it seems like it can be done.
To test this solution I created two projects. ConsoleApplication1 and ClassLibrary1. ConsoleApplication1 does not have a reference (that is visible in Visual Studio) to ClassLibary1 but when building ConsoleApplication1 from Visual Studio it will build then copy the ClassLibary1.dll to the bin folder of ConsoleApplication1.
To import the target file you will go ahead and add this line to the project that you want to build the unreferenced project. This path will be relative to the current project so in my case the target file was at the root of my solution. Make sure you add this after the line <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> because unreferenced.target relies on targets that are setup in Microsoft.CSharp.targets.
<Import Project="..\unreferenced.target" />
Then you will go ahead and create a file name unreferenced.target and add the contents below to the file.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Start another msbuild task to build your unreferenced project -->
<Target Name="BuildBeforeResolveReferences" BeforeTargets="BeforeResolveReferences">
<MSBuild
BuildInParallel="False"
Projects="$(SolutionDir)ClassLibrary1\ClassLibrary1.csproj"
RunEachTargetSeparately="True"
StopOnFirstFailure="False"
UnloadProjectsOnCompletion="False">
</MSBuild>
</Target>
<Target Name="CopyUnreferencedProjectOutput" AfterTargets="Build">
<!-- This item group is here because we do not want it evaluated by msbuild until the ClassLibrary1.csproj has been compiled and its output is in its output directory -->
<ItemGroup>
<!-- Gets a list of all files at the OutputPath that end in .dll if you need the pdbs remove the .dll -->
<!-- To maintain folder structure in the bin folder use <SourceFiles Include="..\ClassLibary1\#(OutputPath)**\*.dll" /> the double ** is a recursive wild card and will look through all directorys -->
<SourceFiles Include="$(MSBuildProjectDirectory)\..\ClassLibrary1\$(OutputPath)*.dll" />
</ItemGroup>
<!-- To make sure the copy maintains folder structure switch it to this copy -->
<!-- <Copy SourceFiles="#(SourceFiles)" DestinationFiles="#(SourceFiles -> '$(MSBuildProjectDirectory)$(OutputPath)%(RecursiveDir)%(Filename)%(Extension)')" /> -->
<Copy SourceFiles="#(SourceFiles)" DestinationFolder="$(MSBuildProjectDirectory)\$(OutputPath)" />
</Target>
<!-- Cleans up all the files when clean is called -->
<Target Name="CleanUnreferenceProjectOutput" BeforeTargets="Clean">
<ItemGroup>
<!-- Removed the .dll from the end of this to clean up the pdbs as well -->
<SourceFiles Include="$(SolutionDir)\ClassLibrary1\$(OutputPath)*" />
<SourceFiles Include="$(SolutionDir)\ConsoleApplication1\$(OutputPath)*.dll" />
</ItemGroup>
<Delete Files="#(SourceFiles)" />
</Target>
</Project>
I think this is the best that can be done. You could extend this to have a list of projects that are not referenced but you want to build but for this example I just left it at one.
EDIT 2: Before getting to the current solution I did extensive research into injecting the reference into the ProjectReference itemgroup before assemblies were resolved. It can be done but you have to set the property BuildInVisualStudio to false because otherwise when the msbuild conditions are evaluted in the ResolveProjectReferences target in Microsoft.Common.Current.targets you will select a MSBuild task that only runs the GetManifest target. I was able to get the solution to build but given my lack of knowledge on what setting BuildInVisualStudio to false entails I opted for the solution above. Also I added a task for cleaning up the files that were moved to the bin folders because clean will only cleanup what {ProjectName}{ProjectExtension}FileListAbsoluteText.txt in the obj folder of your project.
EDIT: After doing some more research into the solution below it will only work from the command line. I am currently looking into why this is occuring.
I don't know if there is a typical way of doing what you are asking for (from IDE), but you have an options to accomplish this manually by editing the *.*proj files.
Each project will emit output (*.dll, *.exe, app.config, etc), and it will be copied to the folder specified in the $(OutputPath) property (internally it will use OutDir property). If you will build a solution, you will have the $(SolutionDir) property, as well as $(SolutionName). So, you can define new msbuild project, which will be referenced by the other ones, and you can set the property $(OutputPath) so that every output will go into one folder (let call it Common.props):
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionDir Condition=" '$(SolutionDir)' == '' ">$(MSBuildThisFileDirectory)<SolutionDir>
<SolutionName Condition=" '$(SolutionName)' == '' " >DefaultSlnName</SolutionName>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<OutputPath>$(SolutionDir)$(SolutionName)\bin\$(Configuration)</OutputPath>
</PropertyGroup>
</Project>
After that, you should import that project by your other projects - *.*proj (you should specify correct path to the project):
<Import Project="..\Common.props" Condition="Exists('..\Common.props')" />
Using common $(OutputPath) property will place all of your binaries to the one folder - this should help to resolve your task.
I've been trying to write an MSBuild task to "compile" CoCo/R .ATG files into C# files which will then get compiled into the executable, this is to replace the pre-build event.
I've managed to get the .ATG -> .cs process working, however something is not right since the generates .cs files do not get compiled.
If I then modify the .ATG file again, the "old" .cs files seems to get compiled then new ones generated.
I'm quite sure I'm missing something that will inform the rest of the build process that these files have changed.
Here is the target definition that I have included in my Visual Studio 2010 project.
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<AvailableItemName Include="BuildATG" />
</ItemGroup>
<PropertyGroup>
<CoreBuildDependsOn>
BuildATGTarget;
$(CoreBuildDependsOn)
</CoreBuildDependsOn>
</PropertyGroup>
<Target Name="BuildATGTarget" Inputs="#(BuildATG)" Outputs="#(BuildATG -> '%(RelativeDir)Parser.cs')">
<Exec Command="Coco.exe %(BuildATG.Identity)" Outputs="%(BuildATG.RelativeDir)Parser.cs" />
</Target>
</Project>
I am completly new to MSBuild, so any advice / pointers would be appreciated.
One possible solution I have found is to do the following changes and add an ItemGroup inside the target.
<Target Name="BuildATGTarget" Inputs="#(BuildATG)" Outputs="#(BuildATG -> '%(RelativeDir)Parser.cs')">
<Exec Command="Coco.exe %(BuildATG.Identity)" Outputs="%(BuildATG.RelativeDir)Parser.cs" />
<ItemGroup>
<Compile Include="%(BuildATG.RelativeDir)Parser.cs" />
<Compile Include="%(BuildATG.RelativeDir)Scanner.cs" />
</ItemGroup>
</Target>
To avoid duplicate files in your build, you also need to mark the files (Parser.cs and Scanner.cs) in the Visual Studio 2010 project with Build Action: None
I'm trying to update my (previously working) pdf-creating web application to use the ABCpdf.NET and ABCpdf.NET Gecko Runtime nuget packages.
I've installed both packages (both are version 8.1.1.6) however when I run my application, I get the following WebSupergoo.ABCpdf8.Internal.PDFException:
Failed to add HTML: Gecko engine hit an error it was unable to recover
from. Possible causes: XULRunner folder is corrupt or is from another
version of ABCpdf.
After installing the ABCpdf.NET Gecko Runtime package, I got a dialog telling me that I would need to manually copy the XULRunner folder into my output directory. In order to achieve this, I added the following to my applications .csproj file:
<Target Name="AfterBuild">
<CallTarget Targets="CopyAbcpdfToDeployFolder" />
</Target>
<Target Name="CopyAbcpdfToDeployFolder">
<ItemGroup>
<SourceDir Include="$(ProjectDir)XULRunner\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(SourceDir)" DestinationFolder="$(WebProjectOutputDir)\$(OutputPath)%(SourceDir.RecursiveDir)\XULRunner" />
</Target>
(This seems to be working correctly - the XULRunner folder and its contents are present in my bin folder after a build)
The line of code that is failing is as follows:
theDoc.AddImageUrl(url);
Can anyone help me get this working?
As it turns out, my changes to the .csproj file we not copying all files into the correct subfolders. In order to copy the folder structure and files recursively, the XML should have looked like this:
<Target Name="AfterBuild">
<CallTarget Targets="CopyXULRunnerToDeployFolder" />
</Target>
<Target Name="CopyXULRunnerToDeployFolder">
<ItemGroup>
<MyFiles Include="XULRunner\**\*.*" />
</ItemGroup>
<Microsoft.Build.Tasks.Copy SourceFiles="#(MyFiles)" DestinationFiles="#(MyFiles->'$(OutputPath)\XULRunner\%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
I was able to accomplish the same outcome with the following MSBuild xml:
<ItemGroup>
<Content Include="XULRunner\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
I fell upon this setup after dealing with issues concerning the building of a package via MSDeploy not including the XULRunner files.
Not sure if there's anything patently wrong with this, but so far it works for me on a multiple staged deployment setup.
I Am trying to add a Post Build MSBuild event to my csproj to do this i am trying to call an MSBuild task from inside the Afterbuild target in the.csproj file
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.-->
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
<Message Text="Copying Files" />
<MSBuild Projects="post.build"
Targets="Copy"
ContinueOnError="false" />
</Target>
This is then the post.build file.
<Project DefaultTargets="Copy"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Copy">
<Message Text="Copying Files inside COPY" />
<CallTarget Targets="CopyToProfile"/> </Target>
</project>
It seems that the csproj cannot call the MSbuild task, can anyone suggest what might be going wrong here. I get the error
error MSB4057: The target "Copy" does
not exist in the project.
So What I eventually got working was.
I did as Martin Suggested and
<Import Project="post.build"/>
However the MSBuild Task still did not function as planned. So I ended up using the
<CallTarget Targets="copy"/>
To Call across the files. This sounds like it is a limitation in VS2008 and is fixed in VS2010.
Are you sure you haven't made the typo in your actual post.build file as well? That is, it should be not . XML is case-sensitive.
Also, I would double-check that the post.build file is placed in the same folder as the .csproj file.