MSBuild ZipDirectory Output Different when Building Solution and Building Individual Project - visual-studio

I'm having an issue with MSBuild ZipDirectory command, where the zipped output file differs between when built by individual project and when built for entire solution.
For example,
The expected zip file looks like below:
A.txt
B.txt
C.txt
The zipped file looks as expected when built as individual project.
However,
When solution is build as a whole,
The zipped file looks like below, missing some files:
A.txt
B.txt
What is causing such issue??

MSBuild ZipDirectory Output Different when Building Solution and
Building Individual Project
I wonder if you use ZipDirectory task to compress some certain files in your project. I have tested the command in different projects in the same solution and did not face the same issue as you said. So please check this:
1) If you just compress some content files in the project, try to create a new folder in Solution Explorer called resource and then put any files you want to compress into this. And remember to set this target executes after build process.
<Target Name="ZipOutputPath" AfterTargets="Build">
<ZipDirectory
SourceDirectory="$(MSBuildProjectDirectory)\resource"
DestinationFile="$(MSBuildProjectDirectory)\output.zip" />
</Target>
2) If you want to compress the files of the output folder, please make sure that you have set Copy to Output Directory of the specific files to Copy if newer.
Note :please check if there are some extra targets which will delete some files like C.txt or there is some extra condidtions to limit this.
Build Solution means that it can build all the projects at the same time so I wonder if some extra projects have some configuration which will cause this behavior in the first project.
3) Besides, you can also try zip task to realize this:
<Target Name="zipfiles" AfterTargets = "Build">
<ItemGroup>
<ZipFiles Include="xxxxx\A.txt" />
<ZipFiles Include="xxxxx\B.txt" />
<ZipFiles Include="xxxxx\C.txt" />
</ItemGroup>
<Zip OutputFilename="$(OutputPath)Project.zip" Files="#(ZipFiles)" />
</Target>
In addition, if all of these did not help, there might be a situation where you might have a problem with your VS environment. Due to it, you can follow these steps:
A) close VS instance, delete .vs hidden folder under the solution path,bin and obj folder. Then restart your solution and then build again to see whether the issue persists.
B) use devenv /safemode to start VS and then test whether the issue is caused by third party extensions, packages.
C) do a repair in VS Installer.
If I misunderstand your issue, please share more detailed info and feel free to let us know.

Related

Visual studio add project reference with lib file

It looks like there has been some work done to add support for visual studio c++ project to project references.
https://developercommunity.visualstudio.com/t/MsBuild-to-resolve-and-copy-ProjectRefer/668834?space=62
If I setup a reference from GoogleTestSample to oqkern I am able to get a bunch of files copied locally.
oqkern.net.dll
oqkern.net.runtimeconfig.json
and also a bunch of other dlls
Is there a way I can get the oqkern.net.lib file to be copied locally as well?
I seem to need that to be able to compile without getting linker errors.
I think the property below takes care of being able to include source files from the referenced project:
I have tried to use the "content file" approach but it didn't seem to work.
<ItemGroup>
<Library Include="..\..\src\oqkern\bin\$(Platform)\$(Configuration)\oqkern.net.lib">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
</Library>
</ItemGroup>
I'm not sure if the content file approach happens soon enough, I need the file copied before the build so things compile.
A pre-build event works:
xcopy /y /d "$(SolutionDir)src\oqkern\bin\$(Platform)\$(Configuration)\oqkern.net.lib" "$(OutDir)"

What is incremental clean in msbuild and when is it triggered?

I am debugging a bug in my build process that happens occasionally but I can't directly reproduce it. I'm using msbuild with teamcity.
I have a dependency hierarchy like this:
Some.Interop.dll
Dependency-> SharedDllABC.dll
SomeService.exe
Depenendcy-> Some.Interop
Usually the final service exectuable gets in its release directory:
Some.Interop
SharedDllABC.Dll
ServiceExectuable.exe
However I can see in our msbuild logs that sometimes the tertiary dependency gets deleted during an Incremental Clean after everything is built resulting in:
Some.Interop
ServiceExectuable.exe
You can see it here in the msbuild log:
[src\SomeService\SomeService.csproj] _TimeStampAfterCompile
[12:32:43]: [src\SomeService\SomeService.csproj] Compile
// some other targets
[12:32:43]: [src\SomeService\SomeService.csproj] _CopyFilesMarkedCopyLocal
[12:32:43]: [_CopyFilesMarkedCopyLocal] Copy
[12:32:43]: [Copy] Copying file from "C:Projects\trunk\src\Some.Interop\bin\Release\Some.Interop.dll" to "bin\Release\Some.Interop.dll".
// some other targets
[src\Project\SomeService\SomeService.csproj] IncrementalClean
[18:54:42]: [IncrementalClean] Delete
[18:54:42]: [Delete] Deleting file "C:\Projects\trunk\src\Project\SomeService\bin\Release\SharedDllABC.dll".
[18:54:42]: [Delete] Deleting file "C:\Projects\trunk\src\Project\SomeServiceService\bin\Release\SharedDllABC.pdb".
[18:54:42]: [src\Project\SomeService\SomeService.csproj] CoreBuild
[18:54:42]: [src\Project\SomeService\SomeService.csproj] AfterBuild
[18:54:42]: [src\Project\SomeService\SomeService.csproj] Build
This is my direct msbuild output, I just changed the project names/dll names to match my example. By the time this Incremental Clean has occurred the SomeService.csproj has already been built. You can see that its not getting copied. However in other msbuild logs it does properly get copied and then the incremental clean doesn't delete it.
I think incrementeal clean from this post is supposed to clean dll's that were created from previous builds, but that doesn't explain how this dll didn't get built when most of the time it does. In visual studio this always works as well.
I guess I just want to know what exactly is Incremental clean, what causes it to kick in, and maybe what things I should look for when debugging a situation like this (assembly versions, timestamps, etc?)
Try the following:
Add:
<Target Name="IncrementalClean" />
to a .targets file that's included in all projects.
From --> https://github.com/Microsoft/msbuild/issues/1054
#Kebabbi recommends a good fix by editing a csproj file. As of MSBuild 15, there is a simple way to make this apply to all CSPROJ files, instead of editing each csproj file.
https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2017
Directory.Build.props and Directory.Build.targets
Prior to MSBuild version 15, if you wanted to provide a new, custom property to projects in your solution, you had to manually add a reference to that property to every project file in the solution. Or, you had to define the property in a .props file and then explicitly import the .props file in every project in the solution, among other things.
However, now you can add a new property to every project in one step by defining it in a single file called Directory.Build.props in the root folder that contains your source. When MSBuild runs, Microsoft.Common.props searches your directory structure for the Directory.Build.props file (and Microsoft.Common.targets looks for Directory.Build.targets). If it finds one, it imports the property. Directory.Build.props is a user-defined file that provides customizations to projects under a directory.
Create a file Directory.Build.props, and place it adjacent to the SLN file.
<Project>
<Target
Name="ForceAssignProjectConfigurationBeforeSplitProjectReferencesByFileExistence_KLUDGE"
BeforeTargets="_SplitProjectReferencesByFileExistence"
DependsOnTargets="AssignProjectConfiguration" />
</Project>
This could be caused by a bug in MsBuild: https://github.com/Microsoft/msbuild/issues/1054.
A fix is proposed in the comments: https://github.com/Microsoft/msbuild/issues/1054#issuecomment-406438561
When MsBuild determines which items to copy from referenced projects, it should do this recursively but does not properly do this.
As a workaround the following can be added to each csproj.
<Target
Name="ForceAssignProjectConfigurationBeforeSplitProjectReferencesByFileExistence_KLUDGE"
BeforeTargets="_SplitProjectReferencesByFileExistence"
DependsOnTargets="AssignProjectConfiguration"
/>
I just spent a few days trying to figure this out with a similar pattern. In our case it was nuget files that were being removed from the output folder.
NugetPackage (that drops files in x86/x64 subfolders in output folder)
LibraryA.dll
Dependency-> NugetPackage
LibraryB.dll
Dependency-> LibraryA.dll
In our case, we have a number of solution files that are built as part of an msbuild script in a certain order.
The problem was that LibraryB.csproj was included in two solution files.
Solution1 builds and output files are all present.
Solution2 builds and sees that LibraryB.dll is present and up to date, so for some reason triggers the IncrementalClean that removes the NugetPackage files from the output folder.
Once I removed the LibraryB.csproj from solution 2, the problem is solved and the files are present in the output folder.

Problem with CruiseControl.net configuration

I started using ccnet to build my project. This is quite new issue for me so I have some problems.
First thing: Why does ccnet copy directory with my project to another directory (ccnet creates new folder named the same as project name included in ccnet.config file and copies to them directory with my project)
Second thing: Dashboard page cannot show reports for recent build (When I click on any item in recent build then I get page: "The page Cannot be found" I suppose that page cannot link files with logs. but I don't know how to link it.
I create one publisher:
<publishers>
<xmllogger logDir="c:\Branches" />
Can anyone help me?
Just a question, does the batch file "C:\Branches\Scripts\Build Release.bat" perform that step?
Because I can't see anything obvious within the CruiseControl config to copy the files into "c:\Program Files\CruiseControl.NET\Sever\TestProject"...
In build Release script I just call devenv to compile my project
Not sure I fully understand the 'first thing' if you can elaborate on it I'll try to help.
On our system it performs an SVN checkout of the code to a specified location and builds it there. Even though our CCNet installation is on the same box as the SVN repository it still needs somewhere separate to build the project.
On the 'second thing' it sounds like you have not set the <webURL> element properly - not a major problem. If you can post your config file that may help (with both issues).
Our CCNet installation pretty much worked out of the box but it is pretty fussy about it's config files. Have you made any changes to the dashboard.config file or is it as installed?
[Edit in response to posted config file]
I can't see anything in this config that will cause CCNet to copy the project to c:\Program Files\CruiseControl.NET\Server\TestProject. It could be something to do with the way you are calling devenv in your batch file - do you specify any paths in there?
Based on your config file and assuming you have an out of the box installation, your <webURL> element should read something like this:
<webURL>http://localhost/ccnet/server/local/testProject/ViewProjectReport.aspx</webURL>
On top of all that I would highly recommend that you drop the use of .bat files and devenv.exe for building your projects. Although this is the way I started with CCNet I quickly found that using NAnt and MSBuild well worth the effort.
I Try explain it more.
I have my local copy of repository on the path: "c:\Branches\trunk"
here is my config file:
<cruiseControl>
<project name="testProject">
<webURL>http://localhost/ccnet/</webURL>
<triggers>
<intervalTrigger name="interval trigger" seconds="600" initialSeconds="30" />
</triggers>
<sourcecontrol type="svn" autoGetSource="true">
<trunkUrl>http://********/svn/general/provider/prototype/Trunk</trunkUrl>
<workingDirectory>C:\Branches\Trunk</workingDirectory>
<password>***********</password>
<username>*************</username>
</sourcecontrol>
<tasks>
<exec>
<description>Compile program</description>
<baseDirectory>C:\Branches\Trunk\</baseDirectory>
<buildTimeoutSeconds>9000</buildTimeoutSeconds>
<executable>C:\Branches\Scripts\Build Release.bat</executable>
</exec>
</tasks>
<publishers>
<xmllogger logDir="C:\Branches\Trunk\Logs" />
</publishers>
<state type="state" directory="C:\Branches\Trunk\Logs"></state>
</project>
</cruisecontrol>
I didn't change anything in dashboard.config File.
cnet copy all folder c:\Branches\Trunk
to new folder c:\Program Files\CruiseControl.NET\Sever\TestProject
First problem was cause because in previous version of config file i use filesystem as sourcecontrol. Right now this problem don't occur.
Second problem is not resolved, But I have one Idea, Does any configuration files should be placed in virtual directory?

Project file with just files and no built output

How can I make a project file (VS 2008) that just has some data files in and has no built output?
I can make an empty project and add my data files to it (which get copied to the output folder
), but it produces an EmptyProject.dll after I do a build. I want just my data files in the output directory and not some empty DLL or EXE.
I want the data files to be the only thing in this project as the project will be shared in a couple of solutions.
Our application is C#. All of our normal code projects are C#.
The data files are schemas (XSD). I want these schemas to be in the output folder, but I don't want them included with an existing project. I would like a project named "Schemas" that has nothing in except the XSD files and does nothing except copy the XSD files to the output folder. I would like this in a project file so that the same schemas project can be referenced in multiple solutions.
I don't know of a way to suppress the creation of the .dll file. BUT... here's an easy workaround. In the project properties, Build Events tab, write a Post-build event command line that will delete the file. Something like:
del path\filename.dll
Expanding on Scott's answer:
Create a new project of type Empty project
In Properties->Application, change Output type to Class Library
In Properties->Build->Advanced, change Debug Info to None
In Properties->Build Events, set the Post-build event command line to del $(TargetPath)
That way, the project creates only a DLL, which gets deleted. At the same time, the "copy to output directory" settings on your data files is respected.
Possibly another way is editing the csproj file by replacing this:
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
with this:
<Target Name="Build" />
<Target Name="Rebuild" />
Then builds don't create anything. It worked for me.
Same general idea should work for any xxproj file. Just replace the <Import Project...> tags with the <Target...> tags.
I'd be interested in knowing if this causes any issues or doesn't work for anyone.
What do you need a project for if you're not building it?
You can use solution folders to "store" files...
Why not just disable building this project for all configurations (use the Configuration Manager) - that way it won't build.
Great stuff. Expanding on Scott > Daniel's answer:
Safe to remove all References and Properties (AssemblyInfo.cs)
If it is a node/grunt/gulp project then you can invoke it in your Build Events > *Post-build event command line * eg: gulp build or gulp clean
Perhaps you can add removal or obj and bin output folders to your node/grunt/gulp clean scripts mitigating the need for del $(TargetPath)

Checking a file out (TFS) for a pre-build action

I've added a pre-build action for an ASP.NET web control (server control) project, that runs jsmin.exe on a set of Javascript files. These output files are part of the source control tree and are embedded into the assembly.
The problem is when the pre-build runs, jsmin can't write the file as it's readonly. Is it possible to check the file out before hand? Or am I forced to set the file's attributes in the command line.
Any improved solution to the problem is welcome.
Update
One small issue with Mehmet's answer -you need to prepend the VS directory:
"$(DevEnvDir)tf" checkout /lock:none "$(ProjectDir)myfile"
If you're using Team Foundation Server, you can use team foundation command line utility (tf.exe) to check out the file(s) during pre-build and then check them back in during post-build. If you're using something else for source control, you can check if they have a command line tool like tf.exe.
If you do not want to check the files in as part of the build (which you normally wouldn't for this sort of thing) then I would simply set the attributes of the .js files before running jsmin on them. The easiest way of setting the files read-writeable is to use the the Attrib task provided by the MSBuild community extensions. The same community extensions also provide a JSCompress task for easily calling JSMin from MSBuild.
Therefore you'd have something like the following (not tested):
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
<!-- rest of TFSBuild.proj file -->
<Target Name="AfterGet">
<Message Text="Compressing Javascript files under "$(SolutionRoot)"." />
<CreateItem Include="$(SolutionRoot)\**\*.js">
<Output TaskParameter="Include" ItemName="JsFiles"/>
</CreateItem>
<Attrib Files="#(JsFiles)" ReadOnly="false"/>
<JSCompress Files="#(JsFiles)" />
</Target>
Note that by modifying the files after getting them may well cause issues if you tried to move to an incremental build.

Resources