I have a folder with a large number of *.xml files.
I need all those files to be zipped each in a separate zip file.
Example:
- file1.xml
- file2.xml
- file3.xml
After msbuild:
- file1.zip
- file2.zip
- file3.zip
Note that I do not need to zip all the files within one ZIP, and the number of .xml files within the folder will vary everytime.
Is there anyway to do this with an automated msbuild task?
Thanks in advance.
Use the Zip task from MSBuild Extension Pack. Then your MSBuild target can be something like:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="ZipFiles">
<UsingTask TaskName="MSBuild.ExtensionPack.Compression.Zip"
AssemblyFile="..\MSBuildExtensionPack\Releases\4.0.4.0\MSBuild.ExtensionPack.dll" />
<Target Name="ZipFiles">
<ItemGroup>
<FilesToZip Include="xmls\**\*.xml"/>
</ItemGroup>
<Message Text="Zipping '%(FilesToZip.Identity)'" Importance="high" />
<MSBuild.ExtensionPack.Compression.Zip TaskAction="Create"
CompressFiles="%(FilesToZip.FullPath)"
ZipFileName="%(FilesToZip.Filename).zip"
RemoveRoot="%(FilesToZip.RootDir)%(FilesToZip.Directory)" />
</Target>
</Project>
Related
Say I have the following ItemGroup in my msbuild file:
<ItemGroup>
<!-- build all the .proto files -->
<MyGroup Include="**/*.txt" MyProperty="[something here to extract metadata for each item]" />
</ItemGroup>
What can I put in the brackets to set the property as the itemgroup is filled? Specifically, I would like to get the project-relative path for the file (without the filename). Is something like this possible?
You can use the well-known item metadata inside the item.
<Project>
<ItemGroup>
<TextFiles Include="**/*.txt"
MyProperty="Included file %(Filename)(Extension: %(Extension)) in directory %(RelativeDir)" />
</ItemGroup>
<Target Name="ListTextFiles">
<Message Importance="high" Text="#(TextFiles->'%(Identity): %(MyProperty)', '%0A')" />
</Target>
</Project>
with a file structure of
fileA.txt
SomeSubfolder\fileB.txt
SomeSubfolder\fileC.txt
prints:
>dotnet msbuild -t:ListTextFiles -nologo
fileA.txt: Included file fileA(Extension: .txt) in directory
SomeSubfolder\fileB.txt: Included file fileB(Extension: .txt) in directory SomeSubfolder\
SomeSubfolder\fileC.txt: Included file fileC(Extension: .txt) in directory SomeSubfolder\
So, I have used MSBuild but this was years ago.
I want to create a Release build for a solution where once built, it will copy all files into a variable set folder "ReleaseDrop" and zip up the contents.
Before zipping, I want to make sure it copies only the necessary files (i.e no pdb, no sln, no csproj, no .cs files (but .cshtml is allowed) or only certain directories and exclude other directories within a directory.
how can I do this?
This should be a start. It specifies a bunch of files to include in a release, copies them to a directory and zips them. For the zip part I used MSBuild Extension Pack since I have it installed anyway, but you could just as well use a prtable version of 7z or so and incoke it with the Exec task.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
<Import Project="$(MSBuildExtensionsPath)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks"/>
<!--default values for properties if not passed-->
<PropertyGroup>
<ProjectDir Condition="'$(ProjectDir) == ''">C:\Projects\MyProject</ProjectDir>
<ReleaseDrop Condition="'$(ReleaseDrop) == ''">c:\Projects\MyProject\ReleaseDrop</ReleaseDrop>
</PropertyGroup>
<!--build list of files to copy-->
<ItemGroup>
<SourceFiles Include="$(ProjectDir)\bin\*.exe" Exclude="$(ProjectDir)\bin\*test*.exe"/>
<SourceFiles Include="$(ProjectDir)\bin\*.cshtml" />
</ItemGroup>
<!--copy files-->
<Target Name="CopyFiles">
<MakeDir Directories="$(ReleaseDrop)" />
<Copy SourceFiles="#(SourceFiles)" DestinationFolder="$(ReleaseDrop)" />
</Target>
<!--after files are copied, list them then zip them-->
<Target Name="MakeRelease" DependsOnTargets="CopyFiles">
<ItemGroup>
<ZipFiles Include="$(ReleaseDrop)\*.*"/>
</ItemGroup>
<Zip ZipFileName="$(ReleaseDrop)\release.zip" Files="#(ZipFiles)" WorkingDirectory="$(ReleaseDrop)"/>
</Target>
</Project>
can be invoked like
msbuild <name of project file> /t:MakeRelease /p:ProjectDir=c:\projects
I know that using MSBuild Extension Pack I can decompress Zip files, but in my project I need to decompress a RAR file.
How can I do this?
Use Exec to extract archive by winrar.exe/rar.exe.
If you have installed WinRar you can extract its installdir from registry otherwise specify where you rar.exe is located.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Target Name="ExtractRar">
<PropertyGroup>
<RarExe>$(registry:HKEY_LOCAL_MACHINE\Software\Winrar#exe32)</RarExe>
<archive>E:\sample.rar</archive>
<targetDir>E:\ExtratedArchive\</targetDir>
</PropertyGroup>
<Exec Command=""$(RarExe)" x "$(archive)" "$(targetDir)"" />
</Target>
</Project>
I have a AfterBuild target that I would like to use for multiple projects in a solution. Is there a way that I can put that target into a .targets file and reference the file in each project.
Below is what I tried which does not seem to work.
Project File:
<Import Project="..\debug.targets"/>
.Targets File:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="AfterBuild">
<PropertyGroup>
<WebsiteDirectory>C:\Inetpub\wwwroot</WebsiteDirectory>
</PropertyGroup>
<ItemGroup>
<output Include=".\**\*.dll" Exclude=".\**\obj\**" />
<output Include=".\**\*.pdb" Exclude=".\**\obj\**" />
<output Include=".\**\*.svc" />
<output Include=".\**\*.xap" />
<output Include=".\**\*.aspx" />
<output Include=".\**\*.js" />
<output Include=".\**\*.config" />
</ItemGroup>
<PropertyGroup>
<VirtualDirectoryPath>$(WebsiteDirectory)\$(RootNamespace)</VirtualDirectoryPath>
</PropertyGroup>
<copy SourceFiles="#(output)" DestinationFiles="#(output->'$(VirtualDirectoryPath)\%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
Use this
<Import Project="$(MSBuildThisFileDirectory)\debug.targets"/>
$(MSBuildThisFile) = The current project file.
$(MSBuildThisFileDirectory) = The directory that contains current project file.
Relative paths in project files are difficult to use depending on what is invoking the project file. Using msbuild directly and the relative path will resolve to the project file. Use VS and the relative path will use the solution file as the base path.
Using $(MSBuildThisFileDirectory) will force the relative path to use a pre-determined beginning path. All you need to do is fill in the rest of the relative path.
What you are doing is fundamentally correct, but ensure that your Import statement is the last Import in the project file.
To verify that the target is being invoked correctly, run msbuild in diag mode from the command line and note the output regarding your target.
msbuild myproj.proj /v:diag
I have created a custom .targets file as below (Just added all the common tasks required in myproj.vcxproj file to .targets file)
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- *******************************************************************************************
Common tasks
******************************************************************************************* -->
<Target Name="H1">
<Exec Command="del /F/Q #(S_PACK_H1)" />
<RemoveDir Directories="#(D_PACK_H1)" />
</Target>
<Target Name="H2">
<Exec Command="del /F/Q #(S_PACK_H2)" />
<RemoveDir Directories="#(D_PACK_H2)" />
</Target>
<Target Name="H11">
<Exec Command="del /F/Q #(S_PACK_H11)" />
<RemoveDir Directories="#(D_PACK_H11)" />
</Target>
</Project>
All the macros/arrays like S_PACK_H1, D_PACK_H11 are defined in myproj.vcxproj file after which I am importing this in myproj.vcxproj file as below
<Import Project="C:\Program Files\MSBuild\MyCompany\Mycustom.targets" />
when I use the below cmd
msbuild myproj.vcxproj /t:H11
it gives an error "error MSB4057: The target "H11" does not exist in the project"
but If I have the same list of tasks in .vcxproj file instead of .targets file then it works fine.
Can I define macros in .vcxproj file and use them in .targets file? Will MSBuild be able to get that definition/value? If not then how do I go about using/passing something defined in vxcproj file in .targets file?
Why is msbuild not able to see my task when it is in .targets file Vs .proj file? what else do I need to do?
There is no obvious reason for this not to work. Yes you can define targets in an imported file and they should be available, regardless of where the import occurs. If you are using MSBuild 4.0 (there is no ToolsVersion attribute on your .targets file above, so I'm not sure) then you can generate a fully preprocessed file, like this:
> msbuild mproj.vcxproj /pp
Look for the preprocessed file in the same folder. Open it up in a text editor and search for your imported content, it should all be there. If not, perhaps the preprocessed file can shed some light into what is going wrong.