Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Centralized place for documents and templates - VS Build Task

0.00/5 (No votes)
27 Jun 2014 1  
How to copy files to central place set in configuration or setup directly with visual studio build task

Introduction

This is used for copying all files from source directory to destination directory using Build Task. Here it accepts configuration file and reads only destination Key in Application Settings.

Background

You should start with these posts, this should explain more principles for Microsoft.Build.Utilities.Task.

http://msdn.microsoft.com/en-us/library/ms366724.aspx

http://bartdesmet.net/blogs/bart/archive/2008/02/15/the-custom-msbuild-task-cookbook.aspx

Why use central place for templates

To have templates (XSLT, doc, etc.) for generating document in one place is good for editing when you have a lot of different components (services and applications) that uses templates. You do not need to search through servers and folders to find where templates are for simple small changes. If it is on central place you always now where to start.

If it is required to be shared across the network, again you have only one place to allow users to access templates. You will not have to adding several network sharing privileges.

Cons: this centralizing place for templates in one folder is setting build and deploys process for copy these templates to one place. In this article I will try to explain it as best I can.

How to

To set up and use this Copy Files build task you need to set in project dir:
1. Open the *.proj file.

2. Add a UsingTask element to the file and specify the details of your task. For example:

<UsingTask TaskName="FileCopyTask" AssemblyFile="$(ProjectDir)..\Assemblies\drej.CopyFiles.dll"  />

3. Save the file.

4. Uncomment <Target Name="AfterBuild"></Target>

5. Add the task element to run your task inside the Target element. For example:

<Target Name="AfterBuild">
    <FileCopyTask />
</Target>

6. Then setup parameters of task. It is requred to have source with destination, or source with configuration file and Config key. 
Configuration Key is read from AppSettings section in config file. For Example:

<FileCopyTask SourceDirectory="$(ProjectDir)..\Templates" ConfigurationFilePath="$(ProjectDir)\App.config" ConfigurationKey="TemplateFolder" />

or

<FileCopyTask SourceDirectory="$(ProjectDir)..\Templates" DestinationDirectory="c:\DocFolder\Templates" />

7. There is one optional parameter OnlyFileTypes where can you set search pattern like this:

<FileCopyTask SourceDirectory="$(ProjectDir)..\Templates" DestinationDirectory="c:\DocFolder\Templates" OnlyFileTypes="*.xml" />

On search pattern you can find more info here: http://msdn.microsoft.com/en-us/library/wz42302f.aspx

How it is done in C#

There are two parts of solution in coping files:

1. Setup of all parameters - source directory, target directory and file types to copy

2. Coping files from source to target destination

Setup of all parameters

Source directory is set up to folder in project to relative destination. This parameter is set to required.

Required]
public string SourceDirectory { get; set; }

If destination directory is set then nothing more is required to be set up. It is just read from project file.

Other method is when Source directory is setup and also config file and then key. Here is the key that you can use environment (Dev, Testing, Release, etc.) to change value of config key and to use it during build. Here is the code for reading key from configuration file.

this.Source = SourceDirectory;
ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap() { ExeConfigFilename = ConfigurationFilePath };
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
if (config.AppSettings.Settings != null
    && config.AppSettings.Settings.Count > 0
    && config.AppSettings.Settings[ConfigurationKey] != null
    && !string.IsNullOrEmpty(config.AppSettings.Settings[ConfigurationKey].Value))
{
    this.Destination = config.AppSettings.Settings[ConfigurationKey].Value;
}

Coping files

Coping files after source and destination is setup is very easy. Just read all the files of the specific type (default search pattern is *.*) and copy it to destination:

FileInfo[] filesToCopy = null;
if (string.IsNullOrEmpty(OnlyFileTypes))
    filesToCopy = sourceDir.GetFiles("*.*", SearchOption.AllDirectories);
else
    filesToCopy = sourceDir.GetFiles(OnlyFileTypes, SearchOption.AllDirectories);

if (filesToCopy != null && filesToCopy.Count() > 0)
{
    string pathToCopy = string.Empty;
    foreach (var file in filesToCopy)
    {
        //Creating destination directory if not exists
        pathToCopy = file.DirectoryName.Replace(sourceDir.FullName, destinationDir.FullName);
        if (!Directory.Exists(pathToCopy))
            Directory.CreateDirectory(pathToCopy);

        pathToCopy = Path.Combine(pathToCopy, file.Name);

        try
        {
            Log.LogMessage(MessageImportance.High, "Copying file\nfrom: {0}\nto: {1}\n********", file.FullName, pathToCopy);
            file.CopyTo(pathToCopy, true);
        }
        catch (Exception ex)
        {
            Log.LogErrorFromException(ex);
        }
    }
}

Summary

Why I used Microsoft.Build.Utilities.Task instead of Console App and Post Build Events!? Only one reason is that I am able to fail build from Build Task. It is easier to show info and errors with Microsoft.Build.Utilities Libraries.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here