using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Text; using System.Text.RegularExpressions; using System.Xml; using System.IO; using Microsoft.Build.Utilities; using Microsoft.Build.Framework; namespace Com.GuyMahieu.MSBuild.Tasks { /// /// Custom MSBuild task to do regular expression searches in a set of files. /// /// Author: Guy Mahieu (http://blog.guymahieu.com) /// /// Brought to MSBuild from NAnt by Chris Eargle. /// /// Feel free to use and improve this, but if you do make improvements, please /// drop me a line (guy.mahieu@gmail.com). /// public class RegexFinder : Task { private string regexPattern; private bool ignoreCase; private ITaskItem[] files; private string outputFile; [Required] public string RegexPattern { get { return regexPattern; } set { regexPattern = value; } } [Required] public string OutputFile { get { return outputFile; } set { outputFile = value; } } public bool IgnoreCase { get { return ignoreCase; } set { ignoreCase = value; } } public ITaskItem[] Files { get { return files; } set { files = value; } } public override bool Execute() { Regex regex = CreateRegularExpression(); XmlElement rootElement = GetRootXmlElement(); LogInfoMessage(); foreach (ITaskItem fileName in files) { ProcessInputFile(fileName.ToString(), regex, rootElement); } SaveResultFile(rootElement); return true; } private void LogInfoMessage() { StringBuilder result = new StringBuilder(); result.AppendFormat("Processing {0} file(s) for matches to pattern: {1}", files.Length, regexPattern); if (ignoreCase) { result.Append(" (case insensitive)"); } else { result.Append(" (case sensitive)"); } Log.LogMessage(MessageImportance.Low, result.ToString()); } private void ProcessInputFile(string fileName, Regex regex, XmlElement rootElement) { using (StreamReader reader = new StreamReader(File.Open(fileName, FileMode.Open, FileAccess.Read))) { string line; int lineNumber = 0; while ((line = reader.ReadLine()) != null) { lineNumber++; if (regex.IsMatch(line)) { RegisterResult(rootElement, fileName, lineNumber, line); } } } } private Regex CreateRegularExpression() { RegexOptions options = RegexOptions.Singleline; if (ignoreCase) { options |= RegexOptions.IgnoreCase; } return new Regex(regexPattern, options); } private void RegisterResult(XmlElement rootElement, string fileName, int lineNumber, string lineData) { XmlDocument doc = rootElement.OwnerDocument; XmlElement matchElement = doc.CreateElement("match"); XmlElement fileNameElement = doc.CreateElement("fileName"); fileNameElement.InnerText = fileName; matchElement.AppendChild(fileNameElement); XmlElement lineNrElement = doc.CreateElement("lineNumber"); lineNrElement.InnerText = lineNumber.ToString(); matchElement.AppendChild(lineNrElement); XmlElement lineDataElement = doc.CreateElement("lineData"); lineDataElement.InnerText = lineData; matchElement.AppendChild(lineDataElement); rootElement.AppendChild(matchElement); } private void SaveResultFile(XmlElement rootElement) { FileInfo output = new FileInfo(outputFile); using (StreamWriter writer = new StreamWriter(output.Open(FileMode.Create, FileAccess.ReadWrite))) { rootElement.OwnerDocument.Save(writer); } } private XmlElement GetRootXmlElement() { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.AppendChild(xmlDoc.CreateNode(XmlNodeType.XmlDeclaration, "", "")); XmlElement element = xmlDoc.CreateElement("regexFinder"); //XmlAttribute baseDirAttribute = xmlDoc.CreateAttribute("basedir"); //baseDirAttribute.Value = files.BaseDirectory.FullName; //element.Attributes.Append(baseDirAttribute); xmlDoc.AppendChild(element); return element; } } }