2 // ConsoleLogger.cs: Outputs to the console
5 // Marek Sieradzki (marek.sieradzki@gmail.com)
7 // (C) 2005 Marek Sieradzki
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Runtime.InteropServices;
32 using System.Collections;
33 using System.Collections.Generic;
36 using System.Security;
38 using Microsoft.Build.Framework;
40 namespace Microsoft.Build.BuildEngine {
41 public class ConsoleLogger : ILogger {
45 LoggerVerbosity verbosity;
46 WriteHandler writeHandler;
50 bool performanceSummary;
52 bool skipProjectStartedText;
53 List<string> errors, warnings;
55 ConsoleColor errorColor, warningColor, eventColor, messageColor, highMessageColor;
57 ColorResetter colorReset;
58 IEventSource eventSource;
59 bool no_message_color, use_colors;
60 bool noItemAndPropertyList;
62 List<BuildEvent> events;
63 Dictionary<string, List<string>> errorsTable;
64 Dictionary<string, List<string>> warningsTable;
65 SortedDictionary<string, PerfInfo> targetPerfTable, tasksPerfTable;
66 string current_events_string;
68 public ConsoleLogger ()
69 : this (LoggerVerbosity.Normal, null, null, null)
73 public ConsoleLogger (LoggerVerbosity verbosity)
74 : this (LoggerVerbosity.Normal, null, null, null)
78 public ConsoleLogger (LoggerVerbosity verbosity,
81 ColorResetter colorReset)
83 this.verbosity = verbosity;
86 this.warningCount = 0;
88 this.writeHandler += new WriteHandler (WriteHandlerFunction);
90 this.writeHandler += write;
91 this.performanceSummary = false;
92 this.showSummary = true;
93 this.skipProjectStartedText = false;
94 errors = new List<string> ();
95 warnings = new List<string> ();
96 this.colorSet = colorSet;
97 this.colorReset = colorReset;
99 events = new List<BuildEvent> ();
100 errorsTable = new Dictionary<string, List<string>> ();
101 warningsTable = new Dictionary<string, List<string>> ();
102 targetPerfTable = new SortedDictionary<string, PerfInfo> ();
103 tasksPerfTable = new SortedDictionary<string, PerfInfo> ();
106 errorColor = ConsoleColor.DarkRed;
107 warningColor = ConsoleColor.DarkYellow;
108 eventColor = ConsoleColor.DarkCyan;
109 messageColor = ConsoleColor.DarkGray;
110 highMessageColor = ConsoleColor.White;
112 // if message color is not set via the env var,
113 // then don't use any color for it.
114 no_message_color = true;
117 if (colorSet == null || colorReset == null)
121 string config = Environment.GetEnvironmentVariable ("XBUILD_COLORS");
122 if (config == null) {
127 if (config == "disable")
131 string [] pairs = config.Split (new char[] {','}, StringSplitOptions.RemoveEmptyEntries);
132 foreach (string pair in pairs) {
133 string [] parts = pair.Split (new char[] {'='}, StringSplitOptions.RemoveEmptyEntries);
134 if (parts.Length != 2)
137 if (parts [0] == "errors")
138 TryParseConsoleColor (parts [1], ref errorColor);
139 else if (parts [0] == "warnings")
140 TryParseConsoleColor (parts [1], ref warningColor);
141 else if (parts [0] == "events")
142 TryParseConsoleColor (parts [1], ref eventColor);
143 else if (parts [0] == "messages") {
144 if (TryParseConsoleColor (parts [1], ref messageColor)) {
145 highMessageColor = GetBrightColorFor (messageColor);
146 no_message_color = false;
152 bool TryParseConsoleColor (string color_str, ref ConsoleColor color)
154 switch (color_str.ToLower ()) {
155 case "black": color = ConsoleColor.Black; break;
157 case "blue": color = ConsoleColor.DarkBlue; break;
158 case "green": color = ConsoleColor.DarkGreen; break;
159 case "cyan": color = ConsoleColor.DarkCyan; break;
160 case "red": color = ConsoleColor.DarkRed; break;
161 case "magenta": color = ConsoleColor.DarkMagenta; break;
162 case "yellow": color = ConsoleColor.DarkYellow; break;
163 case "grey": color = ConsoleColor.DarkGray; break;
165 case "brightgrey": color = ConsoleColor.Gray; break;
166 case "brightblue": color = ConsoleColor.Blue; break;
167 case "brightgreen": color = ConsoleColor.Green; break;
168 case "brightcyan": color = ConsoleColor.Cyan; break;
169 case "brightred": color = ConsoleColor.Red; break;
170 case "brightmagenta": color = ConsoleColor.Magenta; break;
171 case "brightyellow": color = ConsoleColor.Yellow; break;
174 case "brightwhite": color = ConsoleColor.White; break;
175 default: return false;
181 ConsoleColor GetBrightColorFor (ConsoleColor color)
184 case ConsoleColor.DarkBlue: return ConsoleColor.Blue;
185 case ConsoleColor.DarkGreen: return ConsoleColor.Green;
186 case ConsoleColor.DarkCyan: return ConsoleColor.Cyan;
187 case ConsoleColor.DarkRed: return ConsoleColor.Red;
188 case ConsoleColor.DarkMagenta: return ConsoleColor.Magenta;
189 case ConsoleColor.DarkYellow: return ConsoleColor.Yellow;
190 case ConsoleColor.DarkGray: return ConsoleColor.Gray;
191 case ConsoleColor.Gray: return ConsoleColor.White;
193 default: return color;
197 public void ApplyParameter (string parameterName,
198 string parameterValue)
200 // FIXME: what we should do here? in msbuild it isn't
201 // changing "parameters" property
204 public virtual void Initialize (IEventSource eventSource)
206 this.eventSource = eventSource;
208 eventSource.BuildStarted += BuildStartedHandler;
209 eventSource.BuildFinished += BuildFinishedHandler;
211 eventSource.ProjectStarted += PushEvent;
212 eventSource.ProjectFinished += PopEvent;
214 eventSource.TargetStarted += PushEvent;
215 eventSource.TargetFinished += PopEvent;
217 eventSource.TaskStarted += PushEvent;
218 eventSource.TaskFinished += PopEvent;
220 eventSource.MessageRaised += MessageHandler;
221 eventSource.WarningRaised += WarningHandler;
222 eventSource.ErrorRaised += ErrorHandler;
225 public void BuildStartedHandler (object sender, BuildStartedEventArgs args)
227 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
228 WriteLine (String.Empty);
229 WriteLine (String.Format ("Build started {0}.", args.Timestamp));
230 WriteLine ("__________________________________________________");
232 buildStart = args.Timestamp;
237 public void BuildFinishedHandler (object sender, BuildFinishedEventArgs args)
239 BuildFinishedHandlerActual (args);
243 errorsTable.Clear ();
244 warningsTable.Clear ();
245 targetPerfTable.Clear ();
246 tasksPerfTable.Clear ();
253 projectFailed = false;
256 void BuildFinishedHandlerActual (BuildFinishedEventArgs args)
258 if (!IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
263 TimeSpan timeElapsed = args.Timestamp - buildStart;
264 if (performanceSummary || verbosity == LoggerVerbosity.Diagnostic)
265 DumpPerformanceSummary ();
267 if (args.Succeeded == true && !projectFailed) {
268 WriteLine ("Build succeeded.");
270 WriteLine ("Build FAILED.");
272 if (warnings.Count > 0) {
273 WriteLine (Environment.NewLine + "Warnings:");
274 SetColor (warningColor);
276 WriteLine (String.Empty);
277 foreach (KeyValuePair<string, List<string>> pair in warningsTable) {
278 if (!String.IsNullOrEmpty (pair.Key))
279 WriteLine (pair.Key);
281 string indent_str = String.IsNullOrEmpty (pair.Key) ? String.Empty : "\t";
282 foreach (string msg in pair.Value)
283 WriteLine (String.Format ("{0}{1}", indent_str, msg));
285 WriteLine (String.Empty);
291 if (errors.Count > 0) {
292 WriteLine ("Errors:");
293 SetColor (errorColor);
295 WriteLine (String.Empty);
296 foreach (KeyValuePair<string, List<string>> pair in errorsTable) {
297 if (!String.IsNullOrEmpty (pair.Key))
298 WriteLine (pair.Key);
300 string indent_str = String.IsNullOrEmpty (pair.Key) ? String.Empty : "\t";
301 foreach (string msg in pair.Value)
302 WriteLine (String.Format ("{0}{1}", indent_str, msg));
304 WriteLine (String.Empty);
309 if (showSummary == true){
310 WriteLine (String.Format ("\t {0} Warning(s)", warningCount));
311 WriteLine (String.Format ("\t {0} Error(s)", errorCount));
312 WriteLine (String.Empty);
313 WriteLine (String.Format ("Time Elapsed {0}", timeElapsed));
319 public void ProjectStartedHandler (object sender, ProjectStartedEventArgs args)
321 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
322 SetColor (eventColor);
323 WriteLine (String.Format ("Project \"{0}\" ({1} target(s)):", args.ProjectFile,
324 String.IsNullOrEmpty (args.TargetNames) ? "default" : args.TargetNames));
326 DumpProperties (args.Properties);
327 DumpItems (args.Items);
331 public void ProjectFinishedHandler (object sender, ProjectFinishedEventArgs args)
333 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
336 SetColor (eventColor);
337 WriteLine (String.Format ("Done building project \"{0}\".{1}", args.ProjectFile,
338 args.Succeeded ? String.Empty : "-- FAILED"));
340 WriteLine (String.Empty);
343 // no project has failed yet, so update the flag
344 projectFailed = !args.Succeeded;
347 public void TargetStartedHandler (object sender, TargetStartedEventArgs args)
349 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
351 SetColor (eventColor);
352 WriteLine (String.Empty);
353 WriteLine (String.Format ("Target {0}:",args.TargetName));
358 public void TargetFinishedHandler (object sender, TargetFinishedEventArgs args)
360 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed) ||
361 (!args.Succeeded && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal))) {
362 SetColor (eventColor);
363 WriteLine (String.Format ("Done building target \"{0}\" in project \"{1}\".{2}",
364 args.TargetName, args.ProjectFile,
365 args.Succeeded ? String.Empty : "-- FAILED"));
367 WriteLine (String.Empty);
372 public void TaskStartedHandler (object sender, TaskStartedEventArgs args)
374 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed)) {
375 SetColor (eventColor);
376 WriteLine (String.Format ("Task \"{0}\"",args.TaskName));
382 public void TaskFinishedHandler (object sender, TaskFinishedEventArgs args)
385 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed) ||
386 (!args.Succeeded && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal))) {
387 SetColor (eventColor);
389 WriteLine (String.Format ("Done executing task \"{0}\"", args.TaskName));
391 WriteLine (String.Format ("Task \"{0}\" execution -- FAILED", args.TaskName));
396 public void MessageHandler (object sender, BuildMessageEventArgs args)
398 if (IsMessageOk (args)) {
399 if (no_message_color) {
400 ExecutePendingEventHandlers ();
401 WriteLine (args.Message);
403 ExecutePendingEventHandlers ();
404 SetColor (args.Importance == MessageImportance.High ? highMessageColor : messageColor);
405 WriteLine (args.Message);
411 public void WarningHandler (object sender, BuildWarningEventArgs args)
413 string msg = FormatWarningEvent (args);
414 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Quiet)) {
415 ExecutePendingEventHandlers ();
416 SetColor (warningColor);
417 WriteLineWithoutIndent (msg);
422 List<string> list = null;
423 if (!warningsTable.TryGetValue (EventsAsString, out list))
424 warningsTable [EventsAsString] = list = new List<string> ();
430 public void ErrorHandler (object sender, BuildErrorEventArgs args)
432 string msg = FormatErrorEvent (args);
433 if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Quiet)) {
434 ExecutePendingEventHandlers ();
435 SetColor (errorColor);
436 WriteLineWithoutIndent (msg);
441 List<string> list = null;
442 if (!errorsTable.TryGetValue (EventsAsString, out list))
443 errorsTable [EventsAsString] = list = new List<string> ();
449 public void CustomEventHandler (object sender, CustomBuildEventArgs args)
453 private void WriteLine (string message)
456 StringBuilder sb = new StringBuilder ();
457 for (int i = 0; i < indent; i++)
460 string indent_str = sb.ToString ();
462 foreach (string line in message.Split (new string[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries))
463 writeHandler (indent_str + line);
465 writeHandler (message);
469 void PushEvent<T> (object sender, T args) where T: BuildStatusEventArgs
474 void PushEvent<T> (T args) where T: BuildStatusEventArgs
476 BuildEvent be = new BuildEvent {
478 StartHandlerHasExecuted = false,
483 current_events_string = null;
486 void PopEvent<T> (object sender, T finished_args) where T: BuildStatusEventArgs
488 PopEvent (finished_args);
491 void PopEvent<T> (T finished_args) where T: BuildStatusEventArgs
493 if (events.Count == 0)
494 throw new InvalidOperationException ("INTERNAL ERROR: Trying to pop from an empty events stack");
496 BuildEvent be = events [events.Count - 1];
497 if (performanceSummary || verbosity == LoggerVerbosity.Diagnostic) {
498 var args = be.EventArgs;
499 TargetStartedEventArgs tgt_args = args as TargetStartedEventArgs;
500 if (tgt_args != null) {
501 AddPerfInfo (tgt_args.TargetName, args.Timestamp, targetPerfTable);
503 TaskStartedEventArgs tsk_args = args as TaskStartedEventArgs;
504 if (tsk_args != null)
505 AddPerfInfo (tsk_args.TaskName, args.Timestamp, tasksPerfTable);
509 be.ExecuteFinishedHandler (finished_args);
510 events.RemoveAt (events.Count - 1);
511 current_events_string = null;
514 void ExecutePendingEventHandlers ()
516 foreach (var be in events)
517 be.ExecuteStartedHandler ();
520 string EventsToString ()
522 StringBuilder sb = new StringBuilder ();
524 string last_imported_target_file = String.Empty;
525 for (int i = 0; i < events.Count; i ++) {
526 var args = events [i].EventArgs;
527 ProjectStartedEventArgs pargs = args as ProjectStartedEventArgs;
529 sb.AppendFormat ("{0} ({1}) ->\n", pargs.ProjectFile,
530 String.IsNullOrEmpty (pargs.TargetNames) ?
533 last_imported_target_file = String.Empty;
537 TargetStartedEventArgs targs = args as TargetStartedEventArgs;
539 if (targs.TargetFile != targs.ProjectFile && targs.TargetFile != last_imported_target_file)
540 // target from an imported file,
541 // and it hasn't been mentioned as yet
542 sb.AppendFormat ("{0} ", targs.TargetFile);
544 last_imported_target_file = targs.TargetFile;
545 sb.AppendFormat ("({0} target) ->\n", targs.TargetName);
549 return sb.ToString ();
552 void AddPerfInfo (string name, DateTime start, IDictionary<string, PerfInfo> perf_table)
555 if (!perf_table.TryGetValue (name, out pi)) {
556 pi = new PerfInfo ();
557 perf_table [name] = pi;
560 pi.Time += DateTime.Now - start;
564 void DumpPerformanceSummary ()
566 SetColor (eventColor);
567 WriteLine ("Target perfomance summary:");
570 foreach (var pi in targetPerfTable.OrderBy (pair => pair.Value.Time))
571 WriteLine (String.Format ("{0,10:0.000} ms {1,-50} {2,5} calls", pi.Value.Time.TotalMilliseconds, pi.Key, pi.Value.NumberOfCalls));
573 WriteLine (String.Empty);
575 SetColor (eventColor);
576 WriteLine ("Tasks perfomance summary:");
579 foreach (var pi in tasksPerfTable.OrderBy (pair => pair.Value.Time))
580 WriteLine (String.Format ("{0,10:0.000} ms {1,-50} {2,5} calls", pi.Value.Time.TotalMilliseconds, pi.Key, pi.Value.NumberOfCalls));
582 WriteLine (String.Empty);
585 private void WriteLineWithoutIndent (string message)
587 writeHandler (message);
590 private void WriteHandlerFunction (string message)
592 Console.WriteLine (message);
595 void SetColor (ConsoleColor color)
607 private void ParseParameters ()
609 string[] splittedParameters = parameters.Split (';');
610 foreach (string s in splittedParameters ) {
612 case "PerformanceSummary":
613 this.performanceSummary = true;
616 this.showSummary = false;
618 case "NoItemAndPropertyList":
619 this.noItemAndPropertyList = true;
622 throw new ArgumentException ("Invalid parameter : " + s);
627 public virtual void Shutdown ()
629 if (eventSource == null)
632 eventSource.BuildStarted -= BuildStartedHandler;
633 eventSource.BuildFinished -= BuildFinishedHandler;
635 eventSource.ProjectStarted -= PushEvent;
636 eventSource.ProjectFinished -= PopEvent;
638 eventSource.TargetStarted -= PushEvent;
639 eventSource.TargetFinished -= PopEvent;
641 eventSource.TaskStarted -= PushEvent;
642 eventSource.TaskFinished -= PopEvent;
644 eventSource.MessageRaised -= MessageHandler;
645 eventSource.WarningRaised -= WarningHandler;
646 eventSource.ErrorRaised -= ErrorHandler;
649 static bool InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
651 private string FormatErrorEvent (BuildErrorEventArgs args)
653 // For some reason we get an 1-char empty string as Subcategory somtimes.
654 string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
655 string subcat = subprefix == "" ? "" : args.Subcategory;
657 if (args.LineNumber != 0){
658 if (args.ColumnNumber != 0 && !InEmacs)
659 return String.Format ("{0}({1},{2}): {3}{4}error {5}: {6}",
660 args.File, args.LineNumber, args.ColumnNumber,
661 subprefix, subcat, args.Code, args.Message);
663 return String.Format ("{0}({1}): {2}{3}error {4}: {5}",
664 args.File, args.LineNumber,
665 subprefix, subcat, args.Code, args.Message);
667 return String.Format ("{0}: {1}{2}error {3}: {4}", args.File, subprefix, subcat, args.Code,
672 private string FormatWarningEvent (BuildWarningEventArgs args)
674 // For some reason we get an 1-char empty string as Subcategory somtimes.
675 string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
676 string subcat = subprefix == "" ? "" : args.Subcategory;
678 // FIXME: show more complicated args
679 if (args.LineNumber != 0){
681 if (args.ColumnNumber != 0 && !InEmacs) {
682 return String.Format ("{0}({1},{2}): {3}{4}warning {5}: {6}",
683 args.File, args.LineNumber, args.ColumnNumber,
684 subprefix, subcat, args.Code, args.Message);
686 return String.Format ("{0}({1}): {2}{3}warning {4}: {5}",
687 args.File, args.LineNumber,
688 subprefix, subcat, args.Code, args.Message);
690 return String.Format ("{0}: {1} warning {2}: {3}", args.File, args.Subcategory, args.Code,
695 private bool IsMessageOk (BuildMessageEventArgs bsea)
697 if (bsea.Importance == MessageImportance.High && IsVerbosityGreaterOrEqual (LoggerVerbosity.Minimal)) {
699 } else if (bsea.Importance == MessageImportance.Normal && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
701 } else if (bsea.Importance == MessageImportance.Low && IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed)) {
707 private bool IsVerbosityGreaterOrEqual (LoggerVerbosity v)
709 if (v == LoggerVerbosity.Diagnostic) {
710 return LoggerVerbosity.Diagnostic <= verbosity;
711 } else if (v == LoggerVerbosity.Detailed) {
712 return LoggerVerbosity.Detailed <= verbosity;
713 } else if (v == LoggerVerbosity.Normal) {
714 return LoggerVerbosity.Normal <= verbosity;
715 } else if (v == LoggerVerbosity.Minimal) {
716 return LoggerVerbosity.Minimal <= verbosity;
717 } else if (v == LoggerVerbosity.Quiet) {
723 void DumpProperties (IEnumerable properties)
725 if (noItemAndPropertyList || !IsVerbosityGreaterOrEqual (LoggerVerbosity.Diagnostic))
728 SetColor (eventColor);
729 WriteLine (String.Empty);
730 WriteLine ("Initial Properties:");
733 if (properties == null)
736 var dict = new SortedDictionary<string, string> ();
737 foreach (DictionaryEntry de in properties)
738 dict [(string)de.Key] = (string)de.Value;
740 foreach (KeyValuePair<string, string> pair in dict)
741 WriteLine (String.Format ("{0} = {1}", pair.Key, pair.Value));
744 void DumpItems (IEnumerable items)
746 if (noItemAndPropertyList || !IsVerbosityGreaterOrEqual (LoggerVerbosity.Diagnostic) || items == null)
749 SetColor (eventColor);
750 WriteLine (String.Empty);
751 WriteLine ("Initial Items:");
756 var items_table = new SortedDictionary<string, List<ITaskItem>> ();
757 foreach (DictionaryEntry de in items) {
758 string key = (string)de.Key;
759 if (!items_table.ContainsKey (key))
760 items_table [key] = new List<ITaskItem> ();
762 items_table [key].Add ((ITaskItem) de.Value);
765 foreach (string name in items_table.Keys) {
768 foreach (ITaskItem item in items_table [name])
769 WriteLine (item.ItemSpec);
774 public string Parameters {
780 throw new ArgumentNullException ();
782 if (parameters != String.Empty)
787 string EventsAsString {
789 if (current_events_string == null)
790 current_events_string = EventsToString ();
791 return current_events_string;
795 public bool ShowSummary {
796 get { return showSummary; }
797 set { showSummary = value; }
800 public bool SkipProjectStartedText {
801 get { return skipProjectStartedText; }
802 set { skipProjectStartedText = value; }
805 public LoggerVerbosity Verbosity {
806 get { return verbosity; }
807 set { verbosity = value; }
810 protected WriteHandler WriteHandler {
811 get { return writeHandler; }
812 set { writeHandler = value; }
817 public BuildStatusEventArgs EventArgs;
818 public bool StartHandlerHasExecuted;
819 public ConsoleLogger ConsoleLogger;
821 public void ExecuteStartedHandler ()
823 if (StartHandlerHasExecuted)
826 if (EventArgs is ProjectStartedEventArgs)
827 ConsoleLogger.ProjectStartedHandler (null, (ProjectStartedEventArgs)EventArgs);
828 else if (EventArgs is TargetStartedEventArgs)
829 ConsoleLogger.TargetStartedHandler (null, (TargetStartedEventArgs)EventArgs);
830 else if (EventArgs is TaskStartedEventArgs)
831 ConsoleLogger.TaskStartedHandler (null, (TaskStartedEventArgs)EventArgs);
832 else if (!(EventArgs is BuildStartedEventArgs))
833 throw new InvalidOperationException ("Unexpected event on the stack, type: " + EventArgs.GetType ());
835 StartHandlerHasExecuted = true;
838 public void ExecuteFinishedHandler (BuildStatusEventArgs finished_args)
840 if (!StartHandlerHasExecuted)
843 if (EventArgs is ProjectStartedEventArgs)
844 ConsoleLogger.ProjectFinishedHandler (null, finished_args as ProjectFinishedEventArgs);
845 else if (EventArgs is TargetStartedEventArgs)
846 ConsoleLogger.TargetFinishedHandler (null, finished_args as TargetFinishedEventArgs);
847 else if (EventArgs is TaskStartedEventArgs)
848 ConsoleLogger.TaskFinishedHandler (null, finished_args as TaskFinishedEventArgs);
849 else if (!(EventArgs is BuildStartedEventArgs))
850 throw new InvalidOperationException ("Unexpected event on the stack, type: " + EventArgs.GetType ());
855 public TimeSpan Time;
856 public int NumberOfCalls;