MSBuild Extension Pack Zip the folders and subfolders - msbuild

I have to Zip my folders and subfolders Using MSbuild, I was looking at the MSBuild Extension pack, and tried this
<ItemGroup>
<ZipFiles Include="\Test\Web\**\*.*" >
<Group>Release</Group>
</ZipFiles>
</ItemGroup>
<MSBuild.ExtensionPack.Compression.Zip TaskAction="Create" CompressFiles="#(ZipFiles)" ZipFileName="$(WorkingDir)%(ZipFiles.Group).zip"/>
When I do this it just keep adding all the files to root, instead of adding it into the specific subfolder within the zip file.
I am missing something, can anyone help here please.

You need to provide a RemoveRoot property, this property sets the root to remove from the compress files path. (More info)
<ItemGroup>
<ZipFiles Include="\Test\Web\**\*.*" >
<Group>Release</Group>
</ZipFiles>
</ItemGroup>
<MSBuild.ExtensionPack.Compression.Zip
TaskAction="Create"
CompressFiles="#(ZipFiles)"
ZipFileName="$(WorkingDir)%(ZipFiles.Group).zip"
RemoveRoot="\Test\Web"/>

I believe you need to have a value for the RemoveRoot property.

Since, nobody answered early, I went ahead and used 7 Zip, Command line utility, to do that.

Related

File path with "$(TopDir)\**\packages.config"

This sounds really basic but couldn't find any info on internet about it.I am working with msbuild and inside a .proj file I found the following line
<ItemGroup>
<PackageFiles Include="$(TopDir)\**\packages.config" />
</ItemGroup>
I know that ".\" means current directory and "..\" previous one, but what about "**\"?
That 'double star' (i.e. **) in msbuild is used with items.
It means get all sub-directories. In your example code, it can be read as: Under the top directory, get all packages.config files in all sub-directories.
The latest docs are at Microsoft here:
https://learn.microsoft.com/en-us/visualstudio/msbuild/how-to-select-the-files-to-build
This has nothing to do with paths in CMD or DOS. This is how MSBuild's wildcards work. You can read about them here. Basically, ** matches a partial path, so in your case the items include all packages.config from any subfolders of $(TopDir). (And $(TopDir) would be specified in some <PropertyGroup> elsewhere.)

Suppress .codeanalysislog.xml and .lastcodeanalysisuccceeded files from getting dropped

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>

Remove $(Platform) from destination file

I have a code to copy propper configuration file on deploy:
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CopyConfigFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
<Target Name="CopyConfigFiles">
<ItemGroup>
<_ConfigFiles Include="Configurations\*.$(Platform).config" />
<FilesForPackagingFromProject Include="%(_ConfigFiles.Identity)">
<DestinationRelativePath>%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
Is it possible to remove $(Platform) from result files ?
ie.
$(Platform) = Production
Source: connectionString.Production.config
Destination: connectionString.config
An alternative solution would be to actually reference connectionString.config in your project and substitute it with an appropriate version on a pre-build msbuuild step.
We had a similair approach to handling environment-specific configuration files (so we had:
web.production.config
web.staging.config
web.debug.config
However, a pre-build step was used to pick one of this files and overwrite existing web.config files, so when it came to execution/deployment/packaging system dealed with correct environment-specific config file, named web.config.
This approach is well described by Scott Hanselman in his blog post
In my opinion the best thing is "config transformations". They are really easy to learn, very powerful ,you override only the portion of the web.config that is changing for that particular platform, and they are bundled with Visual Studio.
Take a look at this blog
http://blogs.msdn.com/b/webdev/archive/2009/05/04/web-deployment-web-config-transformation.aspx
I hope that helps.

How can I use a batch file to MSBuild solutions in multiple directories at once?

I am an intern with a start-up company. I don't know anything about Batch files, XML files, the command prompt, or msbuild. I only know the basics of C#.
I have been asked to make a batch file that allows a user to build ALL solutions in a directory, with seven subfolders, in one command. I know how to build one solution in a single folder (by using msbuild mysolution.sln), but to build many solutions from seven different folders is beyond me.
It is possible to make a batch file that allows msbuild to find all solution files in the subfolders and build them all at once?
Thanks in advance for anyone who can help.
Save following targets file as buildall.targets in the root of your solutions directory
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets="Default">
<ItemGroup>
<AllFiles Include=".\**\*.sln"/>
</ItemGroup>
<Target Name="Default">
<MSBuild Projects="#(AllFiles)"/>
</Target>
</Project>
Create batch file named BuildAll.cmd with following content: (change path to msbuild.exe depends on .NET Framework version you are using)
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\msbuild buildall.targets
Run/execute BuildAll.cmd
See MSDN: How to: Select the Files to Build for more details on recursive folder traversal, especially "Specifying Inputs with Wildcards" part

How do I import the msbuildcommunitytasks project from another msbuild project with a relative file path?

Please go easy I am new to msbuild and msbuildtasks!
How can I set a property which represents a relative file path to a targets file which I want to import? I need relative references so it will work on all dev machines. But the target for import is trying to use the relative file path internally, which won't work as it is re-evaluated relative to the imported target!
Effectively I am trying to work around the documented behaviour of imported projects:
All relative paths in imported
projects are interpreted relative to
the directory of the imported project.
Therefore, if a project file is
imported into several project files in
different locations, the relative
paths in the imported project file
will be interpreted differently for
each imported project.
There was a similar question at Is it possible to use MSBuild Extension Pack without installation?. That question was how to do the same with the MSBuild Extension Pack, both of which are similar in this aspect. For the Extension Pack you have to declare the property ExtensionTasksPath,and for the Community tasks you have to declare a similar property named MSBuildCommunityTasksLib. So in your case it should look like:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildCommunityTasksLib Condition="'$(MSBuildCommunityTasksLib)' == ''">E:\Data\Development\My Code\Community\MSBuild\CommunityTasks\</MSBuildCommunityTasksLib>
</PropertyGroup>
<Import Project="$(MSBuildCommunityTasksLib)MSBuild.Community.Tasks.Targets"/>
<Target Name="Demo">
<!-- Use the tasks here -->
</Target>
</Project>
Ok, I've found the answer. Essentially you have to set the property MSBuildCommunityTasksPath as a relative path back to the original containing directory.
For example, given a folder structure like this:
Root---project---Build---{My msbuild project}
|
|-Tools---MSBuildCommunityTasks---{Binaries and Targets}
Where :
{My msbuild project} is in Root\Project\Build\
{MSbuildCommunityTasks} is in Root\Project\Tools\MsBuildCommunityTasks
To get the targets project to reference its binaries via the property MSBuildCommunityTasksPath, it will find the tasks file like this:
<PropertyGroup>
<MSBuildCommunityTasksPath>..\MSBuildCommunityTasks\</MSBuildCommunityTasksPath> <!--Relative path back to yourself-->
</PropertyGroup>
Then you can import the targets file with another relative file reference :
<Import Project="..\..\Tools\MSBuildCommunityTasks\MsBuild.Community.Tasks.Targets"/>
#Sayed Ibrahim Hashimi
Talkin about MSBuild4
Just declaring the MSBuildCommunityTasksLib wont suffice cause if u check the MSBuild.Community.Tasks.Targets file the properties are declared as follows
<PropertyGroup>
<MSBuildCommunityTasksPath Condition="'$(MSBuildCommunityTasksPath)' == ''">$(MSBuildExtensionsPath)\MSBuildCommunityTasks</MSBuildCommunityTasksPath>
<MSBuildCommunityTasksLib>$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll</MSBuildCommunityTasksLib>
</PropertyGroup>
So if U only over ride the MSBuildCommunityTasksLib it will again get over ridden in the MSBuild.Community.Tasks.Targets file as it is not conditional
So u HAVE TO ALSO OVERRIDE MSBuildCommunityTasksPath so that its proerty is NOT SET FROM MSBuildExtensionsPath but from ur custom path.
Correst me if I m wrong
This appears to be one answer:
http://social.msdn.microsoft.com/forums/en-US/msbuild/thread/feb782e3-72ae-4476-9011-617796f217b6
But this (if I understand it correctly) appears to be a ridiculous solution. To get the paths to work I need to change the imported project references? What would happen if I wanted to reference the imported project from third project in another folder?!?
I'm a noob at msbuild if I'm quite honest however I've just solved my own problem I had with this. I was turning one of the targets into its own project and it wasn't finding the paths for the msbuild community paths. If you look at your original project you may find something like this
<PropertyGroup>
<ExtensionTasksPath>./</ExtensionTasksPath>
<MSBuildCommunityTasksPath>./</MSBuildCommunityTasksPath>
</PropertyGroup>
<Import Project="MSBuildExtensionPack\MSBuild.ExtensionPack.tasks"/>
<Import Project="MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
Copy this code into your new project and it should work.
I just wanted to add, since i cannot comment (rep), that to do a path to your particular project you can use $(SolutionDir) on your property group like so:
$(SolutionDir)\My Code\Community\MSBuild\CommunityTasks\
This way its not tied down to a specific drive and can be based off of the location of the project relative to your solutions directory structure.
Also thanks for the answer above it helped me in my project with the addition above.