这是一个存根的自定义 MSBuild 任务。您可以将“RunMyCustomKeeperLogic”逻辑更改为您想要的任何内容。作为一个愚蠢的例子,我将其命名为“保留每 5 个文件”。
将文件放回“.msbuild”世界后,您可以复制/移动对它们做任何您想做的事情。
namespace GranadaCoder.Framework.CrossDomain.MSBuild.Tasks.IO
{
using System.Collections.Generic;
using Microsoft.Build.Utilities;
public abstract class FileBasedTaskBase : Task
{
/// <summary>
/// Converts the delimited source file string to and IList.
/// </summary>
/// <param name="sourceFilesString">The source files string.</param>
/// <returns></returns>
protected IList<string> ConvertSourceFileStringToList(string sourceFilesString)
{
IList<string> returnList = sourceFilesString.Split(';');
return returnList;
}
/// <summary>
/// Task Entry Point.
/// </summary>
/// <returns></returns>
public override bool Execute()
{
AbstractExecute();
return !Log.HasLoggedErrors;
}
protected abstract bool AbstractExecute();
}
}
namespace GranadaCoder.Framework.CrossDomain.MSBuild.Tasks.IO//.CustomFileKeepTask
{
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.IO;
using System.Security;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
public class CustomFileKeepTask : FileBasedTaskBase
{
private static readonly string ROOT_DIRECTORY = "myrootdir";
private static readonly string FULL_PATH = "myfullpath";
private static readonly string FILE_NAME = "myfilename";
private static readonly string DIRECTORY = "mydirectory";
private static readonly string EXTENSION = "myextension";
private static readonly string KEEPER = "mykeeper";
/// <summary>
/// Gets or sets the source files.
/// </summary>
/// <value>The source files.</value>
[Required]
public string SourceFiles { get; set; }
/// <summary>
/// Gets the file versions as a Task Output property.
/// </summary>
/// <value>The file versions.</value>
[Output]
public ITaskItem[] FilteredFiles
{ get; private set; }
/// <summary>
/// Task Entry Point.
/// </summary>
/// <returns></returns>
protected override bool AbstractExecute()
{
InternalExecute();
return !Log.HasLoggedErrors;
}
/// <summary>
/// Internal Execute Wrapper.
/// </summary>
private void InternalExecute()
{
IList<string> files = null;
if (String.IsNullOrEmpty(this.SourceFiles))
{
Log.LogWarning("No SourceFiles specified");
return;
}
if (!String.IsNullOrEmpty(this.SourceFiles))
{
Console.WriteLine(this.SourceFiles);
files = base.ConvertSourceFileStringToList(this.SourceFiles);
}
List<FileInfoWrapper> fiws = new List<FileInfoWrapper>();
foreach (string f in files)
{
FileInfoWrapper fiw = null;
fiw = this.DetermineExtraInformation(f);
fiws.Add(fiw);
}
fiws = RunMyCustomKeeperLogic(fiws);
ArrayList itemsAsStringArray = new ArrayList();
foreach (var fiw in fiws.Where(x => x.IsAKeeper == true))
{
IDictionary currentMetaData = new System.Collections.Hashtable();
currentMetaData.Add(ROOT_DIRECTORY, fiw.RootDirectory);
currentMetaData.Add(FULL_PATH, fiw.FullPath);
currentMetaData.Add(FILE_NAME, fiw.FileName);
currentMetaData.Add(DIRECTORY, fiw.Directory);
currentMetaData.Add(EXTENSION, fiw.Extension);
string trueOrFalse = fiw.IsAKeeper.ToString();
currentMetaData.Add(KEEPER, trueOrFalse);
itemsAsStringArray.Add(new TaskItem(trueOrFalse, currentMetaData));
}
this.FilteredFiles = (ITaskItem[])itemsAsStringArray.ToArray(typeof(ITaskItem));
}
private List<FileInfoWrapper> RunMyCustomKeeperLogic(List<FileInfoWrapper> fiws)
{
int counter = 0;
foreach (var fiw in fiws)
{
if(counter++ % 5 == 0)
{
fiw.IsAKeeper = true;
}
}
return fiws;
}
/// <summary>
/// Determines the file version.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <returns>File version or 0.0.0.0 if value cannot be determined</returns>
private FileInfoWrapper DetermineExtraInformation(string fileName)
{
FileInfoWrapper fiw = new FileInfoWrapper();
fiw.Directory = string.Empty;
fiw.Extension = string.Empty;
fiw.FileName = string.Empty;
fiw.FullPath = string.Empty;
fiw.RootDirectory = string.Empty;
fiw.IsAKeeper = false;
try
{
if (System.IO.File.Exists(fileName))
{
fiw.Extension = System.IO.Path.GetExtension(fileName);
fiw.FileName = System.IO.Path.GetFileNameWithoutExtension(fileName);
fiw.FullPath = fileName;// System.IO.Path.GetFileName(fileName);
fiw.RootDirectory = System.IO.Path.GetPathRoot(fileName);
//Take the full path and remove the root directory to mimic the DotNet default behavior of '%filename'
fiw.Directory = System.IO.Path.GetDirectoryName(fileName).Remove(0, fiw.RootDirectory.Length);
}
}
catch (Exception ex)
{
if (ex is IOException
|| ex is UnauthorizedAccessException
|| ex is PathTooLongException
|| ex is DirectoryNotFoundException
|| ex is SecurityException)
{
Log.LogWarning("Error trying to determine file version " + fileName + ". " + ex.Message);
}
else
{
Log.LogErrorFromException(ex);
throw;
}
}
return fiw;
}
/// <summary>
/// Internal wrapper class to hold file properties of interest.
/// </summary>
internal sealed class FileInfoWrapper
{
public string Directory { get; set; }
public string Extension { get; set; }
public string FileName { get; set; }
public string FullPath { get; set; }
public string RootDirectory { get; set; }
public bool IsAKeeper { get; set; }
}
}
}
这是一个示例 .msbuild(或 .proj 或 .xml)文件来调用上述内容。
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="AllTargetsWrapper" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask AssemblyFile="GranadaCoder.Framework.CrossDomain.MSBuild.dll" TaskName="CustomFileKeepTask"/>
<Target Name="AllTargetsWrapper">
<CallTarget Targets="CustomFileKeepTask1" />
<CallTarget Targets="CustomFileKeepTask2" />
</Target>
<PropertyGroup>
<WorkingCheckout>c:\Program Files\MSBuild</WorkingCheckout>
</PropertyGroup>
<ItemGroup>
<MyTask1IncludeFiles Include="$(WorkingCheckout)\**\*.*" />
</ItemGroup>
<Target Name="CustomFileKeepTask1">
<CustomFileKeepTask SourceFiles="@(MyTask1IncludeFiles)" >
<Output TaskParameter="FilteredFiles" ItemName="MyFilteredFileItemNames"/>
</CustomFileKeepTask>
<Message Text=" MyFilteredFileItemNames MetaData "/>
<Message Text=" ------------------------------- "/>
<Message Text=" "/>
<Message Text="directory: "/>
<Message Text="@(MyFilteredFileItemNames->'%(mydirectory)')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="extension: "/>
<Message Text="@(MyFilteredFileItemNames->'%(myextension)')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="filename: "/>
<Message Text="@(MyFilteredFileItemNames->'%(myfilename)')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="fullpath: "/>
<Message Text="@(MyFilteredFileItemNames->'%(myfullpath)')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="rootdir: "/>
<Message Text="@(MyFilteredFileItemNames->'%(myrootdir)')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="FilteredFile: "/>
<Message Text="@(MyFilteredFileItemNames->'%(mykeeper)')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="rootdir + directory + filename + extension: "/>
<Message Text="@(MyFilteredFileItemNames->'%(myrootdir)%(mydirectory)%(myfilename)%(myextension)')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="List of files using special characters (carriage return)"/>
<Message Text="@(MyFilteredFileItemNames->'"%(myfullpath)"' , '%0D%0A')"/>
<Message Text=" "/>
<Message Text=" "/>
</Target>
<ItemGroup>
<MyTask2IncludeFiles Include="c:\windows\notepad.exe" />
</ItemGroup>
<Target Name="CustomFileKeepTask2">
<CustomFileKeepTask SourceFiles="@(MyTask2IncludeFiles)" >
<Output TaskParameter="FilteredFiles" PropertyName="SingleFileFilteredFile"/>
</CustomFileKeepTask>
<Message Text="SingleFileFilteredFile = $(SingleFileFilteredFile) "/>
</Target>
</Project>