Extract RAR from MSBUILD script - msbuild

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>

Related

Nuget targets, how to send a renamed content file to solution output folder?

I have created a Nuget package with a default json configuration file, 'config.json.pp'. On installation it is transformed and added as content; 'config.json'. I have also added a targets file in the build folder of the package, it renames the config file based on the assembly root namespace the package is installed in:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ConfigFile Include="config.json"/>
</ItemGroup>
<Target Name="CopyConfigFile" AfterTargets="Build;Rebuild">
<Copy SourceFiles="#(ConfigFile)" DestinationFiles ="#(ConfigFile->'$(OutDir)\$(RootNameSpace)%(Extension)')" />
</Target>
</Project>
When the assembly is build in a solution with more assemblies, it is not added to the output directory, only to the bin\$(configuration) folder of the assembly where the package is installed.
How can I add the file to the output directory of the main application of the solution?
You can use the link metadata to do this:
<ItemGroup>
<Content Include="config.json"
Link="$(RootNameSpace)%(Extension)"
CopyToOutputDirectory="PreserveNewest"
Visible="False"
Condition="Exists('config.json')" />
</ItemGroup>

Use MSBuild Targets to copy files recursively from NuGet package

I have a .targets file in my NuGet package build folder which is then automatically included in the project that consumes the NuGet package.
I want this .targets file to copy some folders on post-build. The following script shows how that is done, but the output I get is wrong because %(RecursiveDir) starts at the first wild-card which I used for the version number of the package.
My question: How can I specify the version of MyPackage in the .targets file dynamically so that I can remove the first wildcard?
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="AfterBuild">
<ItemGroup>
<!-- MyPackage.* should be replaced by MyPackage.1.0.0.4534. But the version is set by NuGet.exe pack -Version -->
<FilesToCopy Include="$(SolutionDir)packages\MyPackage.*\myfolder\**\*.*"/>
</ItemGroup>
<Copy SourceFiles="#(FilesToCopy)" DestinationFolder="$(SolutionDir)bin\$(Configuration)\myfolder\%(RecursiveDir)"/>
</Target>
</Project>
To avoid having to the package version you could use the MSBuildThisFileDirectory property instead.
The MSBuildThisFileDirectory property gives you the directory where the .targets file is so you can change the <FilesToCopy> element to use a path relative to that directory and you do not have to use the version number.
<FilesToCopy Include="$(MSBuildThisFileDirectory)myfolder\**\*.*"/>

Creating a Release drop

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

Move AfterBuild target to a .targets file

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

MsBuild Zip every file in directory in separate Zip files

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>