Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
We are still using CruiseControl.Net. My TFS bias hasn't been strong enough to overcome my laziness… yet. However, I we have changed the ccnet build to use MSBuild for the bulk of the process. The MSBuild project is then checked into the solution so we can maintain this with the code base.
This means the output of the build is 99% MSBuild log. The standard MSBuild logger that ccnet uses, is, to say the least, pretty ugly. Fortunately, there is a better logger created by Christian Rodemeyer. Unfortunately, this is a little buggy. Fortunately, the source code is provided.
SO! To cut a long story short, if you are using this logger and seeing this error:
MSBUILD : error MSB4015: The build stopped unexpectedly because the "ReusableLogger" logger failed unexpectedly during shutdown. System.ArgumentException: Illegal characters in path. at System.IO.Path.CheckInvalidPathChars(String path) at System.IO.Path.GetDirectoryName(String path) at Rodemeyer.MsBuildToCCNet.MsBuildToCCNetLogger.WriteErrorsOrWarnings(XmlWriter w, String type, IEnumerable list) at Rodemeyer.MsBuildToCCNet.MsBuildToCCNetLogger.WriteProject(XmlWriter w, Project p) at Rodemeyer.MsBuildToCCNet.MsBuildToCCNetLogger.WriteLog(XmlWriter w) at Rodemeyer.MsBuildToCCNet.MsBuildToCCNetLogger.Shutdown() at Microsoft.Build.Evaluation.ProjectCollection.ReusableLogger.Shutdown() at Microsoft.Build.BackEnd.Logging.LoggingService.ShutdownLogger(ILogger logger)
Then get the source for the logger from here and in the Logger.cs file, replace WriteErrorsOrWarnings() with the following:
static void WriteErrorsOrWarnings(XmlWriter w, string type, IEnumerable list)
{
foreach (ErrorOrWarningBase ew in list)
w.WriteStartElement(type);
w.WriteAttributeString("code", ew.Code);
w.WriteAttributeString("message", ew.Text);
if (ew.File != null)
string dir = "_unknown_";
string name = ew.File;
try
dir = Path.GetDirectoryName(ew.File);
}
catch { }
name = Path.GetFileName(ew.File);
w.WriteAttributeString("dir", dir);
w.WriteAttributeString("name", name);
w.WriteAttributeString("pos", "(" + XmlConvert.ToString(ew.Line) + ", " + XmlConvert.ToString(ew.Column) + ")");
w.WriteEndElement();