From d78eb62de72bf59eb1c993b8d7e6bd3d4932c2ff Mon Sep 17 00:00:00 2001 From: Jeremy Morren Date: Fri, 21 Jun 2024 16:58:09 -0400 Subject: [PATCH 1/4] Updated to MSBuild V17 --- Directory.Build.props | 11 +- global.json | 2 +- .../BinaryLogger/EvaluationLocation.cs | 302 ------------------ .../BinaryLogger/ProfilerResult.cs | 109 ------- .../ProjectEvaluationFinishedEventArgs.cs | 45 --- .../ProjectEvaluationStartedEventArgs.cs | 36 --- .../BinaryLogger/ProjectImportedEventArgs.cs | 55 ---- .../BinaryLogger/TargetBuiltReason.cs | 31 -- .../BinaryLogger/TargetSkippedEventArgs.cs | 53 --- .../MsBuildPipeLogger.Logger.csproj | 19 +- .../ParameterParser.cs | 4 +- .../BuildEventArgsReaderProxy.cs | 34 -- .../MsBuildPipeLogger.Server.csproj | 6 +- .../PipeLoggerServer.cs | 4 +- .../MsBuildPipeLogger.Logger.Tests.csproj | 5 +- .../ParameterParserFixture.cs | 14 + .../MsBuildPipeLogger.Tests.Client.csproj | 5 +- .../MsBuildPipeLogger.Tests.Client/Program.cs | 12 + .../IntegrationFixture.cs | 27 +- .../MsBuildPipeLogger.Tests.csproj | 1 + 20 files changed, 80 insertions(+), 695 deletions(-) delete mode 100644 src/MsBuildPipeLogger.Logger/BinaryLogger/EvaluationLocation.cs delete mode 100644 src/MsBuildPipeLogger.Logger/BinaryLogger/ProfilerResult.cs delete mode 100644 src/MsBuildPipeLogger.Logger/BinaryLogger/ProjectEvaluationFinishedEventArgs.cs delete mode 100644 src/MsBuildPipeLogger.Logger/BinaryLogger/ProjectEvaluationStartedEventArgs.cs delete mode 100644 src/MsBuildPipeLogger.Logger/BinaryLogger/ProjectImportedEventArgs.cs delete mode 100644 src/MsBuildPipeLogger.Logger/BinaryLogger/TargetBuiltReason.cs delete mode 100644 src/MsBuildPipeLogger.Logger/BinaryLogger/TargetSkippedEventArgs.cs delete mode 100644 src/MsBuildPipeLogger.Server/BuildEventArgsReaderProxy.cs diff --git a/Directory.Build.props b/Directory.Build.props index 6f68a21..e53a9bb 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -19,12 +19,19 @@ true true true + + - - + + + + $(NoWarn);NU1701;CS8632 + + 17.5.0 + \ No newline at end of file diff --git a/global.json b/global.json index 51a6483..2aa85a4 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "6.0.100", + "version": "8.0.100", "rollForward": "latestMinor", "allowPrerelease": false } diff --git a/src/MsBuildPipeLogger.Logger/BinaryLogger/EvaluationLocation.cs b/src/MsBuildPipeLogger.Logger/BinaryLogger/EvaluationLocation.cs deleted file mode 100644 index 770791b..0000000 --- a/src/MsBuildPipeLogger.Logger/BinaryLogger/EvaluationLocation.cs +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -//----------------------------------------------------------------------- -// -// Location for different elements tracked by the evaluation profiler. -//----------------------------------------------------------------------- - -using System; -using System.Collections.Generic; - -namespace Microsoft.Build.Framework.Profiler -{ - /// - /// Evaluation main phases used by the profiler. - /// - /// - /// Order matters since the profiler pretty printer orders profiled items from top to bottom using - /// the pass they belong to. - /// - public enum EvaluationPass : byte - { - TotalEvaluation = 0, - TotalGlobbing = 1, - InitialProperties = 2, - Properties = 3, - ItemDefinitionGroups = 4, - Items = 5, - LazyItems = 6, - UsingTasks = 7, - Targets = 8 - } - - /// - /// The kind of the evaluated location being tracked. - /// - public enum EvaluationLocationKind : byte - { - Element = 0, - Condition = 1, - Glob = 2 - } - - /// - /// Represents a location for different evaluation elements tracked by the EvaluationProfiler. - /// -#if FEATURE_BINARY_SERIALIZATION - [Serializable] -#endif - public struct EvaluationLocation - { - /// - /// Default descriptions for locations that are used in case a description is not provided. - /// - private static readonly Dictionary PassDefaultDescription = - new Dictionary - { - { EvaluationPass.TotalEvaluation, "Total evaluation" }, - { EvaluationPass.TotalGlobbing, "Total evaluation for globbing" }, - { EvaluationPass.InitialProperties, "Initial properties (pass 0)" }, - { EvaluationPass.Properties, "Properties (pass 1)" }, - { EvaluationPass.ItemDefinitionGroups, "Item definition groups (pass 2)" }, - { EvaluationPass.Items, "Items (pass 3)" }, - { EvaluationPass.LazyItems, "Lazy items (pass 3.1)" }, - { EvaluationPass.UsingTasks, "Using tasks (pass 4)" }, - { EvaluationPass.Targets, "Targets (pass 5)" }, - }; - - /// - public long Id { get; } - - /// - public long? ParentId { get; } - - /// - public EvaluationPass EvaluationPass { get; } - - /// - public string EvaluationPassDescription { get; } - - /// - public string File { get; } - - /// - public int? Line { get; } - - /// - public string ElementName { get; } - - /// - public string ElementDescription { get; } - - /// - public EvaluationLocationKind Kind { get; } - - /// - public bool IsEvaluationPass => File == null; - - /// - public static EvaluationLocation CreateLocationForCondition( - long? parentId, - EvaluationPass evaluationPass, - string evaluationDescription, - string file, - int? line, - string condition) - { - return new EvaluationLocation(parentId, evaluationPass, evaluationDescription, file, line, "Condition", condition, kind: EvaluationLocationKind.Condition); - } - - /// - public static EvaluationLocation CreateLocationForGlob( - long? parentId, - EvaluationPass evaluationPass, - string evaluationDescription, - string file, - int? line, - string globDescription) - { - return new EvaluationLocation(parentId, evaluationPass, evaluationDescription, file, line, "Glob", globDescription, kind: EvaluationLocationKind.Glob); - } - - /// - public static EvaluationLocation CreateLocationForAggregatedGlob() - { - return new EvaluationLocation( - EvaluationPass.TotalGlobbing, - PassDefaultDescription[EvaluationPass.TotalGlobbing], - file: null, - line: null, - elementName: null, - elementDescription: null, - kind: EvaluationLocationKind.Glob); - } - - /// - /// Constructs a generic evaluation location. - /// - /// - /// Used by serialization/deserialization purposes. - /// - public EvaluationLocation( - long id, - long? parentId, - EvaluationPass evaluationPass, - string evaluationPassDescription, - string file, - int? line, - string elementName, - string elementDescription, - EvaluationLocationKind kind) - { - Id = id; - ParentId = parentId == EmptyLocation.Id ? null : parentId; // The empty location doesn't count as a parent id, since it's just a dummy starting point - EvaluationPass = evaluationPass; - EvaluationPassDescription = evaluationPassDescription; - File = file; - Line = line; - ElementName = elementName; - ElementDescription = elementDescription; - Kind = kind; - } - - /// - /// Constructs a generic evaluation location based on a (possibly null) parent Id. - /// - /// - /// A unique Id gets assigned automatically - /// Used by serialization/deserialization purposes. - /// - public EvaluationLocation(long? parentId, EvaluationPass evaluationPass, string evaluationPassDescription, string file, int? line, string elementName, string elementDescription, EvaluationLocationKind kind) - : this(EvaluationIdProvider.GetNextId(), parentId, evaluationPass, evaluationPassDescription, file, line, elementName, elementDescription, kind) - { - } - - /// - /// Constructs a generic evaluation location with no parent. - /// - /// - /// A unique Id gets assigned automatically - /// Used by serialization/deserialization purposes. - /// - public EvaluationLocation(EvaluationPass evaluationPass, string evaluationPassDescription, string file, int? line, string elementName, string elementDescription, EvaluationLocationKind kind) - : this(null, evaluationPass, evaluationPassDescription, file, line, elementName, elementDescription, kind) - { - } - - /// - /// An empty location, used as the starting instance. - /// - public static EvaluationLocation EmptyLocation { get; } = CreateEmptyLocation(); - - /// - public EvaluationLocation WithEvaluationPass(EvaluationPass evaluationPass, string passDescription = null) - { - return new EvaluationLocation( - Id, - evaluationPass, - passDescription ?? PassDefaultDescription[evaluationPass], - File, - Line, - ElementName, - ElementDescription, - Kind); - } - - /// - public EvaluationLocation WithParentId(long? parentId) - { - // Simple optimization. If the new parent id is the same as the current one, then we just return this - if (parentId == ParentId) - { - return this; - } - - return new EvaluationLocation( - Id, - parentId, - EvaluationPass, - EvaluationPassDescription, - File, - Line, - ElementName, - ElementDescription, - Kind); - } - - /// - public EvaluationLocation WithFile(string file) - { - return new EvaluationLocation(Id, EvaluationPass, EvaluationPassDescription, file, null, null, null, Kind); - } - - /// - public EvaluationLocation WithFileLineAndCondition(string file, int? line, string condition) - { - return CreateLocationForCondition(Id, EvaluationPass, EvaluationPassDescription, file, line, condition); - } - - /// - public EvaluationLocation WithGlob(string globDescription) - { - return CreateLocationForGlob(Id, EvaluationPass, EvaluationPassDescription, File, Line, globDescription); - } - - /// - public override bool Equals(object obj) - { - if (obj is EvaluationLocation evaluationLocation) - { - EvaluationLocation other = evaluationLocation; - return - Id == other.Id - && ParentId == other.ParentId - && EvaluationPass == other.EvaluationPass - && EvaluationPassDescription == other.EvaluationPassDescription - && string.Equals(File, other.File, StringComparison.OrdinalIgnoreCase) - && Line == other.Line - && ElementName == other.ElementName - && ElementDescription == other.ElementDescription - && Kind == other.Kind; - } - return false; - } - - /// - public override string ToString() - { - return - $"{Id}\t{ParentId?.ToString() ?? string.Empty}\t{EvaluationPassDescription ?? string.Empty}\t{File ?? string.Empty}\t{Line?.ToString() ?? string.Empty}\t{ElementName ?? string.Empty}\tDescription:{ElementDescription}\t{EvaluationPassDescription}"; - } - - /// - public override int GetHashCode() - { - int hashCode = 1198539463; - hashCode = (hashCode * -1521134295) + base.GetHashCode(); - hashCode = (hashCode * -1521134295) + Id.GetHashCode(); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(ParentId); - hashCode = (hashCode * -1521134295) + EvaluationPass.GetHashCode(); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(EvaluationPassDescription); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(File); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Line); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(ElementName); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(ElementDescription); - return (hashCode * -1521134295) + Kind.GetHashCode(); - } - - private static EvaluationLocation CreateEmptyLocation() - { - return new EvaluationLocation( - EvaluationIdProvider.GetNextId(), - null, - default(EvaluationPass), - null, - null, - null, - null, - null, - default(EvaluationLocationKind)); - } - } -} diff --git a/src/MsBuildPipeLogger.Logger/BinaryLogger/ProfilerResult.cs b/src/MsBuildPipeLogger.Logger/BinaryLogger/ProfilerResult.cs deleted file mode 100644 index aae50b0..0000000 --- a/src/MsBuildPipeLogger.Logger/BinaryLogger/ProfilerResult.cs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -//----------------------------------------------------------------------- -// -// The result profiling an evaluation. -//----------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; - -namespace Microsoft.Build.Framework.Profiler -{ - /// - /// Result of profiling an evaluation. - /// -#if FEATURE_BINARY_SERIALIZATION - [Serializable] -#endif - public struct ProfilerResult - { - /// - public IReadOnlyDictionary ProfiledLocations { get; } - - /// - public ProfilerResult(IDictionary profiledLocations) - { - ProfiledLocations = new ReadOnlyDictionary(profiledLocations); - } - - /// - public override bool Equals(object obj) - { - if (!(obj is ProfilerResult)) - { - return false; - } - - ProfilerResult result = (ProfilerResult)obj; - - return (ProfiledLocations == result.ProfiledLocations) - || (ProfiledLocations.Count == result.ProfiledLocations.Count - && !ProfiledLocations.Except(result.ProfiledLocations).Any()); - } - - /// - public override int GetHashCode() - { - return ProfiledLocations.Keys.Aggregate(0, (acum, location) => acum + location.GetHashCode()); - } - } - - /// - /// Result of timing the evaluation of a given element at a given location. - /// -#if FEATURE_BINARY_SERIALIZATION - [Serializable] -#endif - public struct ProfiledLocation - { - /// - public TimeSpan InclusiveTime { get; } - - /// - public TimeSpan ExclusiveTime { get; } - - /// - public int NumberOfHits { get; } - - /// - public ProfiledLocation(TimeSpan inclusiveTime, TimeSpan exclusiveTime, int numberOfHits) - { - InclusiveTime = inclusiveTime; - ExclusiveTime = exclusiveTime; - NumberOfHits = numberOfHits; - } - - /// - public override bool Equals(object obj) - { - if (!(obj is ProfiledLocation)) - { - return false; - } - - ProfiledLocation location = (ProfiledLocation)obj; - return InclusiveTime.Equals(location.InclusiveTime) - && ExclusiveTime.Equals(location.ExclusiveTime) - && NumberOfHits == location.NumberOfHits; - } - - /// - public override int GetHashCode() - { - int hashCode = -2131368567; - hashCode = (hashCode * -1521134295) + base.GetHashCode(); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(InclusiveTime); - hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(ExclusiveTime); - return (hashCode * -1521134295) + NumberOfHits.GetHashCode(); - } - - /// - public override string ToString() - { - return $"[{InclusiveTime} - {ExclusiveTime}]: {NumberOfHits} hits"; - } - } -} diff --git a/src/MsBuildPipeLogger.Logger/BinaryLogger/ProjectEvaluationFinishedEventArgs.cs b/src/MsBuildPipeLogger.Logger/BinaryLogger/ProjectEvaluationFinishedEventArgs.cs deleted file mode 100644 index ee9819d..0000000 --- a/src/MsBuildPipeLogger.Logger/BinaryLogger/ProjectEvaluationFinishedEventArgs.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using Microsoft.Build.Framework.Profiler; - -namespace Microsoft.Build.Framework -{ - /// - /// Arguments for the project evaluation finished event. - /// -#if FEATURE_BINARY_SERIALIZATION - [Serializable] -#endif - public sealed class ProjectEvaluationFinishedEventArgs : BuildStatusEventArgs - { - /// - /// Initializes a new instance of the ProjectEvaluationFinishedEventArgs class. - /// - public ProjectEvaluationFinishedEventArgs() - { - } - - /// - /// Initializes a new instance of the ProjectEvaluationFinishedEventArgs class. - /// - public ProjectEvaluationFinishedEventArgs(string message, params object[] messageArgs) - : base(message, null, null, DateTime.UtcNow, messageArgs) - { - } - - /// - /// Gets or sets the full path of the project that started evaluation. - /// - public string ProjectFile { get; set; } - - /// - /// The result of profiling a project. - /// - /// - /// Null if profiling is not turned on. - /// - public ProfilerResult? ProfilerResult { get; set; } - } -} diff --git a/src/MsBuildPipeLogger.Logger/BinaryLogger/ProjectEvaluationStartedEventArgs.cs b/src/MsBuildPipeLogger.Logger/BinaryLogger/ProjectEvaluationStartedEventArgs.cs deleted file mode 100644 index f2ba729..0000000 --- a/src/MsBuildPipeLogger.Logger/BinaryLogger/ProjectEvaluationStartedEventArgs.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; - -namespace Microsoft.Build.Framework -{ - /// - /// Arguments for the project evaluation started event. - /// -#if FEATURE_BINARY_SERIALIZATION - [Serializable] -#endif - public class ProjectEvaluationStartedEventArgs : BuildStatusEventArgs - { - /// - /// Initializes a new instance of the ProjectEvaluationStartedEventArgs class. - /// - public ProjectEvaluationStartedEventArgs() - { - } - - /// - /// Initializes a new instance of the ProjectEvaluationStartedEventArgs class. - /// - public ProjectEvaluationStartedEventArgs(string message, params object[] messageArgs) - : base(message, null, null, DateTime.UtcNow, messageArgs) - { - } - - /// - /// Gets or sets the full path of the project that started evaluation. - /// - public string ProjectFile { get; set; } - } -} \ No newline at end of file diff --git a/src/MsBuildPipeLogger.Logger/BinaryLogger/ProjectImportedEventArgs.cs b/src/MsBuildPipeLogger.Logger/BinaryLogger/ProjectImportedEventArgs.cs deleted file mode 100644 index d1a7f6e..0000000 --- a/src/MsBuildPipeLogger.Logger/BinaryLogger/ProjectImportedEventArgs.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; - -namespace Microsoft.Build.Framework -{ - /// - /// Arguments for the project imported event. - /// -#if FEATURE_BINARY_SERIALIZATION - [Serializable] -#endif - public class ProjectImportedEventArgs : BuildMessageEventArgs - { - /// - /// Initializes a new instance of the ProjectImportedEventArgs class. - /// - public ProjectImportedEventArgs() - { - } - - /// - /// Initializes a new instance of the ProjectImportedEventArgs class. - /// - public ProjectImportedEventArgs( - int lineNumber, - int columnNumber, - string message, - params object[] messageArgs) - : base(null, null, null, lineNumber, columnNumber, 0, 0, message, null, null, MessageImportance.Low, DateTime.UtcNow, messageArgs) - { - } - - /// - /// Gets or sets the original value of the Project attribute. - /// - public string UnexpandedProject { get; set; } - - /// - /// Gets or sets the full path to the project file that was imported. Will be. null - /// if the import statement was a glob and no files matched, or the condition (if any) evaluated - /// to false. - /// - public string ImportedProjectFile { get; set; } - - /// - /// Gets or sets if this import was ignored. Ignoring imports is controlled by. - /// ProjectLoadSettings. This is only set when an import would have been included - /// but was ignored to due being invalid. This does not include when a globbed import returned - /// no matches, or a conditioned import that evaluated to false. - /// - public bool ImportIgnored { get; set; } - } -} \ No newline at end of file diff --git a/src/MsBuildPipeLogger.Logger/BinaryLogger/TargetBuiltReason.cs b/src/MsBuildPipeLogger.Logger/BinaryLogger/TargetBuiltReason.cs deleted file mode 100644 index dd4b87c..0000000 --- a/src/MsBuildPipeLogger.Logger/BinaryLogger/TargetBuiltReason.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.Build.Framework -{ - /// - /// The reason that a target was built by its parent target. - /// - public enum TargetBuiltReason - { - /// - /// This wasn't built on because of a parent. - /// - None, - - /// - /// The target was part of the parent's BeforeTargets list. - /// - BeforeTargets, - - /// - /// The target was part of the parent's DependsOn list. - /// - DependsOn, - - /// - /// The target was part of the parent's AfterTargets list. - /// - AfterTargets - } -} diff --git a/src/MsBuildPipeLogger.Logger/BinaryLogger/TargetSkippedEventArgs.cs b/src/MsBuildPipeLogger.Logger/BinaryLogger/TargetSkippedEventArgs.cs deleted file mode 100644 index 926e9f4..0000000 --- a/src/MsBuildPipeLogger.Logger/BinaryLogger/TargetSkippedEventArgs.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; - -namespace Microsoft.Build.Framework -{ - /// - /// Arguments for the target skipped event. - /// -#if FEATURE_BINARY_SERIALIZATION - [Serializable] -#endif - public class TargetSkippedEventArgs : BuildMessageEventArgs - { - /// - /// Initializes a new instance of the TargetSkippedEventArgs class. - /// - public TargetSkippedEventArgs() - { - } - - /// - /// Initializes a new instance of the TargetSkippedEventArgs class. - /// - public TargetSkippedEventArgs( - string message, - params object[] messageArgs) - : base(null, null, null, 0, 0, 0, 0, message, null, null, MessageImportance.Low, DateTime.UtcNow, messageArgs) - { - } - - /// - /// Gets or sets the name of the target being skipped. - /// - public string TargetName { get; set; } - - /// - /// Gets or sets the parent target of the target being skipped. - /// - public string ParentTarget { get; set; } - - /// - /// File where this target was declared. - /// - public string TargetFile { get; set; } - - /// - /// Why the parent target built this target. - /// - public TargetBuiltReason BuildReason { get; set; } - } -} diff --git a/src/MsBuildPipeLogger.Logger/MsBuildPipeLogger.Logger.csproj b/src/MsBuildPipeLogger.Logger/MsBuildPipeLogger.Logger.csproj index c3856f9..4fa14b8 100644 --- a/src/MsBuildPipeLogger.Logger/MsBuildPipeLogger.Logger.csproj +++ b/src/MsBuildPipeLogger.Logger/MsBuildPipeLogger.Logger.csproj @@ -1,24 +1,19 @@  - netstandard2.0 + netstandard2.0 MsBuildPipeLogger + 9 A logger for MSBuild that sends event data over anonymous or named pipes. - - + + - - <_Parameter1>MsBuildPipeLogger.Logger.Tests - - - <_Parameter1>MsBuildPipeLogger.Tests - - - <_Parameter1>MsBuildPipeLogger.Tests.Client - + + + \ No newline at end of file diff --git a/src/MsBuildPipeLogger.Logger/ParameterParser.cs b/src/MsBuildPipeLogger.Logger/ParameterParser.cs index 749cbdb..fe67e15 100644 --- a/src/MsBuildPipeLogger.Logger/ParameterParser.cs +++ b/src/MsBuildPipeLogger.Logger/ParameterParser.cs @@ -56,11 +56,11 @@ public static IPipeWriter GetPipeFromParameters(string parameters) internal static KeyValuePair[] ParseParameters(string parameters) { string[] segments = parameters.Split(';'); - if (segments.Length < 1 || segments.Length > 2) + if (segments.Length is < 1 or > 2) { throw new LoggerException("Unexpected number of parameters"); } - return segments.Select(x => ParseParameter(x)).ToArray(); + return segments.Select(ParseParameter).ToArray(); } private static KeyValuePair ParseParameter(string parameter) diff --git a/src/MsBuildPipeLogger.Server/BuildEventArgsReaderProxy.cs b/src/MsBuildPipeLogger.Server/BuildEventArgsReaderProxy.cs deleted file mode 100644 index 983f79c..0000000 --- a/src/MsBuildPipeLogger.Server/BuildEventArgsReaderProxy.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.IO; -using System.Reflection; -using Microsoft.Build.Framework; -using Microsoft.Build.Logging; - -namespace MsBuildPipeLogger -{ - internal class BuildEventArgsReaderProxy - { - private readonly Func _read; - - public BuildEventArgsReaderProxy(BinaryReader reader) - { - // Use reflection to get the Microsoft.Build.Logging.BuildEventArgsReader.Read() method - object argsReader; - Type buildEventArgsReader = typeof(BinaryLogger).GetTypeInfo().Assembly.GetType("Microsoft.Build.Logging.BuildEventArgsReader"); - ConstructorInfo readerCtor = buildEventArgsReader.GetConstructor(new[] { typeof(BinaryReader) }); - if (readerCtor != null) - { - argsReader = readerCtor.Invoke(new[] { reader }); - } - else - { - readerCtor = buildEventArgsReader.GetConstructor(new[] { typeof(BinaryReader), typeof(int) }); - argsReader = readerCtor.Invoke(new object[] { reader, 7 }); - } - MethodInfo readMethod = buildEventArgsReader.GetMethod("Read"); - _read = (Func)readMethod.CreateDelegate(typeof(Func), argsReader); - } - - public BuildEventArgs Read() => _read(); - } -} diff --git a/src/MsBuildPipeLogger.Server/MsBuildPipeLogger.Server.csproj b/src/MsBuildPipeLogger.Server/MsBuildPipeLogger.Server.csproj index c991eef..239a7bf 100644 --- a/src/MsBuildPipeLogger.Server/MsBuildPipeLogger.Server.csproj +++ b/src/MsBuildPipeLogger.Server/MsBuildPipeLogger.Server.csproj @@ -5,11 +5,9 @@ A logger for MSBuild that sends event data over anonymous or named pipes. - + - - <_Parameter1>MsBuildPipeLogger.Tests - + \ No newline at end of file diff --git a/src/MsBuildPipeLogger.Server/PipeLoggerServer.cs b/src/MsBuildPipeLogger.Server/PipeLoggerServer.cs index f066be7..2de5e27 100644 --- a/src/MsBuildPipeLogger.Server/PipeLoggerServer.cs +++ b/src/MsBuildPipeLogger.Server/PipeLoggerServer.cs @@ -17,7 +17,7 @@ public abstract class PipeLoggerServer : EventArgsDispatcher, IPipe where TPipeStream : PipeStream { private readonly BinaryReader _binaryReader; - private readonly BuildEventArgsReaderProxy _buildEventArgsReader; + private readonly BuildEventArgsReader _buildEventArgsReader; internal PipeBuffer Buffer { get; } = new PipeBuffer(); @@ -43,7 +43,7 @@ protected PipeLoggerServer(TPipeStream pipeStream, CancellationToken cancellatio { PipeStream = pipeStream; _binaryReader = new BinaryReader(Buffer); - _buildEventArgsReader = new BuildEventArgsReaderProxy(_binaryReader); + _buildEventArgsReader = new BuildEventArgsReader(_binaryReader, 7); CancellationToken = cancellationToken; Thread readerThread = new Thread(() => diff --git a/tests/MsBuildPipeLogger.Logger.Tests/MsBuildPipeLogger.Logger.Tests.csproj b/tests/MsBuildPipeLogger.Logger.Tests/MsBuildPipeLogger.Logger.Tests.csproj index 3d88739..ce6b437 100644 --- a/tests/MsBuildPipeLogger.Logger.Tests/MsBuildPipeLogger.Logger.Tests.csproj +++ b/tests/MsBuildPipeLogger.Logger.Tests/MsBuildPipeLogger.Logger.Tests.csproj @@ -3,8 +3,9 @@ net6.0 - - + + + diff --git a/tests/MsBuildPipeLogger.Logger.Tests/ParameterParserFixture.cs b/tests/MsBuildPipeLogger.Logger.Tests/ParameterParserFixture.cs index 21abdcc..1c218b2 100644 --- a/tests/MsBuildPipeLogger.Logger.Tests/ParameterParserFixture.cs +++ b/tests/MsBuildPipeLogger.Logger.Tests/ParameterParserFixture.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using Microsoft.Build.Framework; +using Microsoft.Build.Locator; using MsBuildPipeLogger; using NUnit.Framework; using Shouldly; @@ -11,6 +13,18 @@ namespace MsBuildPipeLogger.Logger.Tests [TestFixture] public class ParameterParserFixture { + static ParameterParserFixture() + { + if (MSBuildLocator.IsRegistered) + { + return; + } + VisualStudioInstance instance = MSBuildLocator.QueryVisualStudioInstances() + .OrderByDescending(instance => instance.Version) + .First(); + MSBuildLocator.RegisterInstance(instance); + } + [TestCase("1234")] [TestCase(" 1234 ")] [TestCase("handle=1234")] diff --git a/tests/MsBuildPipeLogger.Tests.Client/MsBuildPipeLogger.Tests.Client.csproj b/tests/MsBuildPipeLogger.Tests.Client/MsBuildPipeLogger.Tests.Client.csproj index bbb8c7a..2bfa9e5 100644 --- a/tests/MsBuildPipeLogger.Tests.Client/MsBuildPipeLogger.Tests.Client.csproj +++ b/tests/MsBuildPipeLogger.Tests.Client/MsBuildPipeLogger.Tests.Client.csproj @@ -4,8 +4,9 @@ net6.0 - - + + + diff --git a/tests/MsBuildPipeLogger.Tests.Client/Program.cs b/tests/MsBuildPipeLogger.Tests.Client/Program.cs index 2437372..d582dbb 100644 --- a/tests/MsBuildPipeLogger.Tests.Client/Program.cs +++ b/tests/MsBuildPipeLogger.Tests.Client/Program.cs @@ -1,14 +1,26 @@ using System; using System.Diagnostics; +using System.Linq; using Microsoft.Build.Framework; +using Microsoft.Build.Locator; namespace MsBuildPipeLogger.Tests.Client { internal class Program { public static int Main(string[] args) + { + VisualStudioInstance instance = MSBuildLocator.QueryVisualStudioInstances() + .OrderByDescending(instance => instance.Version) + .First(); + MSBuildLocator.RegisterInstance(instance); + return Run(args); + } + + private static int Run(string[] args) { Console.WriteLine(string.Join("; ", args)); + int messages = int.Parse(args[1]); try { diff --git a/tests/MsBuildPipeLogger.Tests/IntegrationFixture.cs b/tests/MsBuildPipeLogger.Tests/IntegrationFixture.cs index df877f8..fbf392a 100644 --- a/tests/MsBuildPipeLogger.Tests/IntegrationFixture.cs +++ b/tests/MsBuildPipeLogger.Tests/IntegrationFixture.cs @@ -6,6 +6,7 @@ using System.Text; using System.Threading; using Microsoft.Build.Framework; +using Microsoft.Build.Locator; using Microsoft.Build.Logging; using NUnit.Framework; using Shouldly; @@ -16,6 +17,18 @@ namespace MsBuildPipeLogger.Tests [NonParallelizable] public class IntegrationFixture { + static IntegrationFixture() + { + if (MSBuildLocator.IsRegistered) + { + return; + } + VisualStudioInstance instance = MSBuildLocator.QueryVisualStudioInstances() + .OrderByDescending(instance => instance.Version) + .First(); + MSBuildLocator.RegisterInstance(instance); + } + private static readonly int[] MessageCounts = { 0, 1, 100000 }; [Test] @@ -27,7 +40,7 @@ public void SerializesData([ValueSource(nameof(MessageCounts))] int messageCount BinaryWriter binaryWriter = new BinaryWriter(memory); BuildEventArgsWriter writer = new BuildEventArgsWriter(binaryWriter); BinaryReader binaryReader = new BinaryReader(memory); - BuildEventArgsReaderProxy reader = new BuildEventArgsReaderProxy(binaryReader); + BuildEventArgsReader reader = new BuildEventArgsReader(binaryReader, 7); List eventArgs = new List(); // When @@ -147,18 +160,26 @@ private int RunClientProcess(IPipeLoggerServer server, string arguments, int mes { process.StartInfo.FileName = "dotnet"; process.StartInfo.Arguments = $"MsBuildPipeLogger.Tests.Client.dll {arguments} {messages}"; - process.StartInfo.WorkingDirectory = Path.GetDirectoryName(typeof(IntegrationFixture).Assembly.Location).Replace("MsBuildPipeLogger.Tests", "MsBuildPipeLogger.Tests.Client"); + string directory = Path.GetDirectoryName(typeof(IntegrationFixture).Assembly.Location); + directory = directory!.Replace("MsBuildPipeLogger.Tests", "MsBuildPipeLogger.Tests.Client"); + process.StartInfo.WorkingDirectory = directory; process.StartInfo.CreateNoWindow = true; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; + process.EnableRaisingEvents = true; process.OutputDataReceived += (s, e) => TestContext.WriteLine(e.Data); - process.ErrorDataReceived += (s, e) => TestContext.WriteLine(e.Data); + process.ErrorDataReceived += (s, e) => + { + TestContext.WriteLine(e.Data); + process.Kill(); + }; process.Start(); TestContext.WriteLine($"Started process {process.Id}"); process.BeginOutputReadLine(); + process.BeginErrorReadLine(); server.ReadAll(); } diff --git a/tests/MsBuildPipeLogger.Tests/MsBuildPipeLogger.Tests.csproj b/tests/MsBuildPipeLogger.Tests/MsBuildPipeLogger.Tests.csproj index c37cf9c..66a01f5 100644 --- a/tests/MsBuildPipeLogger.Tests/MsBuildPipeLogger.Tests.csproj +++ b/tests/MsBuildPipeLogger.Tests/MsBuildPipeLogger.Tests.csproj @@ -3,6 +3,7 @@ net6.0 + From 5b39d5b39ace19b51c411aa6820c95d5fc295481 Mon Sep 17 00:00:00 2001 From: Jeremy Morren Date: Fri, 21 Jun 2024 17:07:25 -0400 Subject: [PATCH 2/4] Added Directory.Build.targets --- Directory.Build.targets | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Directory.Build.targets diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000..c1df222 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,2 @@ + + \ No newline at end of file From bc21b0ec4629aa3ed43415636720ca433182e7ff Mon Sep 17 00:00:00 2001 From: Jeremy Morren Date: Wed, 3 Jul 2024 07:56:00 -0400 Subject: [PATCH 3/4] Updated readme --- Directory.Build.targets | 1 + README.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index c1df222..ae416f1 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,2 +1,3 @@ + \ No newline at end of file diff --git a/README.md b/README.md index a00ac28..8558125 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ server.AnyEventRaised += (s, e) => Console.WriteLine(e.Message); // Note you can also call MSBuild straight from the CLI, you just need to know the pipe handle to pass it to the logger Process process = new Process(); process.StartInfo.FileName = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin"; -process.StartInfo.Arguments = $"/noconlog /logger:MsBuildPipeLogger,\"C:\Path\To\MsBuildPipeLogger.Logger.dll\";{pipeHandle}"; +process.StartInfo.Arguments = $"/noconlog /logger:MsBuildPipeLogger.PipeLogger,\"C:\Path\To\MsBuildPipeLogger.Logger.dll\";{pipeHandle}"; // ...other process settings like working directory process.Start(); @@ -77,7 +77,7 @@ server.AnyEventRaised += (s, e) => Console.WriteLine(e.Message); // Note you can also call MSBuild straight from the CLI, you just need to know the pipe handle to pass it to the logger Process process = new Process(); process.StartInfo.FileName = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin"; -process.StartInfo.Arguments = $"/noconlog /logger:MsBuildPipeLogger.Logger,\"C:\Path\To\MsBuildPipeLogger.Logger.dll\";name=Mario;server=MyServerName"; +process.StartInfo.Arguments = $"/noconlog /logger:MsBuildPipeLogger.PipeLogger,\"C:\Path\To\MsBuildPipeLogger.Logger.dll\";name=Mario;server=MyServerName"; // ...other process settings like working directory process.Start(); From 26b34f837473b69163d1260c19d8b6f7c7923ab1 Mon Sep 17 00:00:00 2001 From: Jeremy Morren Date: Wed, 3 Jul 2024 10:23:51 -0400 Subject: [PATCH 4/4] Added Helper StartReadAll method --- src/MsBuildPipeLogger.Server/PipeLoggerServer.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/MsBuildPipeLogger.Server/PipeLoggerServer.cs b/src/MsBuildPipeLogger.Server/PipeLoggerServer.cs index 2de5e27..5e6368f 100644 --- a/src/MsBuildPipeLogger.Server/PipeLoggerServer.cs +++ b/src/MsBuildPipeLogger.Server/PipeLoggerServer.cs @@ -117,6 +117,15 @@ public void ReadAll() } } + public void BeginReadAll() + { + Thread thread = new Thread(ReadAll) + { + IsBackground = true + }; + thread.Start(); + } + /// public void Dispose() {