Deprecate binfmt in build event args (#8917)

* Fix to properly serialize TargetFinishedEventArgs.TargetOutput
* New extended EventArgs for custom events data
* Make ExternalProject*EventArgs serialize without BinaryFormatter
* Issue warnings only on dotnetcore runtime.
* Make deser constructors internal

---------

Co-authored-by: YuliiaKovalova <ykovalova@microsoft.com>
Co-authored-by: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com>
Co-authored-by: Ladi Prosek <ladi.prosek@gmail.com>
This commit is contained in:
Roman Konecny 2023-08-09 16:58:02 +02:00 коммит произвёл GitHub
Родитель 60363d0313
Коммит f121098b3b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
47 изменённых файлов: 1798 добавлений и 369 удалений

Просмотреть файл

@ -13,6 +13,9 @@
<PackageVersion Include="BenchmarkDotNet" Version="0.13.1" />
<PackageVersion Update="BenchmarkDotNet" Condition="'$(BenchmarkDotNetVersion)' != ''" Version="$(BenchmarkDotNetVersion)" />
<PackageVersion Include="FluentAssertions" Version="6.11.0" />
<PackageVersion Update="FluentAssertions" Condition="'$(FluentAssertionsVersion)' != ''" Version="$(FluentAssertionsVersion)" />
<PackageVersion Include="LargeAddressAware" Version="1.0.5" />
<PackageVersion Update="LargeAddressAware" Condition="'$(LargeAddressAwareVersion)' != ''" Version="$(LargeAddressAwareVersion)" />

Просмотреть файл

@ -0,0 +1,163 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.Build.BackEnd.Logging;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
using Microsoft.Build.UnitTests;
using Shouldly;
using Xunit;
using Xunit.Abstractions;
using Xunit.NetCore.Extensions;
using static Microsoft.Build.UnitTests.ObjectModelHelpers;
#nullable disable
namespace Microsoft.Build.Engine.UnitTests.BackEnd
{
public class BuildManager_Logging_Tests : IDisposable
{
private string _mainProject = @"
<Project>
<Target Name=`MainTarget`>
<MSBuild Projects=`{0}` Targets=`ChildTarget` />
</Target>
</Project>";
private string _childProjectWithCustomBuildEvent = $@"
<Project>
<UsingTask TaskName=""CustomBuildEventTask"" AssemblyFile=""{Assembly.GetExecutingAssembly().Location}"" />
<Target Name=`ChildTarget`>
<CustomBuildEventTask />
</Target>
</Project>";
/// <summary>
/// The mock logger for testing.
/// </summary>
private readonly MockLogger _logger;
/// <summary>
/// The standard build manager for each test.
/// </summary>
private readonly BuildManager _buildManager;
/// <summary>
/// The project collection used.
/// </summary>
private readonly ProjectCollection _projectCollection;
private readonly TestEnvironment _env;
private readonly ITestOutputHelper _output;
/// <summary>
/// SetUp
/// </summary>
public BuildManager_Logging_Tests(ITestOutputHelper output)
{
_output = output;
// Ensure that any previous tests which may have been using the default BuildManager do not conflict with us.
BuildManager.DefaultBuildManager.Dispose();
_logger = new MockLogger(output);
_buildManager = new BuildManager();
_projectCollection = new ProjectCollection();
_env = TestEnvironment.Create(output);
}
[DotNetOnlyTheory]
[InlineData("1", true)]
[InlineData("0", false)]
[InlineData(null, true)]
public void Build_WithCustomBuildArgs_NetCore(string envVariableValue, bool isWarningExpected)
=> TestCustomEventWarning<BuildErrorEventArgs>(envVariableValue, isWarningExpected);
[WindowsFullFrameworkOnlyTheory]
[InlineData("1", true)]
[InlineData("0", false)]
[InlineData(null, false)]
public void Build_WithCustomBuildArgs_Framework(string envVariableValue, bool isWarningExpected) =>
TestCustomEventWarning<BuildWarningEventArgs>(envVariableValue, isWarningExpected);
private void TestCustomEventWarning<T>(string envVariableValue, bool isWarningExpected) where T : LazyFormattedBuildEventArgs
{
var testFiles = _env.CreateTestProjectWithFiles(string.Empty, new[] { "main", "child1" }, string.Empty);
ILoggingService service = LoggingService.CreateLoggingService(LoggerMode.Synchronous, 1);
service.RegisterLogger(_logger);
_env.SetEnvironmentVariable("MSBUILDCUSTOMBUILDEVENTWARNING", envVariableValue);
_env.SetEnvironmentVariable("MSBUILDNOINPROCNODE", "1");
_buildManager.BeginBuild(BuildParameters);
try
{
var child1ProjectPath = testFiles.CreatedFiles[1];
var cleanedUpChildContents = CleanupFileContents(_childProjectWithCustomBuildEvent);
File.WriteAllText(child1ProjectPath, cleanedUpChildContents);
var mainProjectPath = testFiles.CreatedFiles[0];
var cleanedUpMainContents = CleanupFileContents(string.Format(_mainProject, child1ProjectPath));
File.WriteAllText(mainProjectPath, cleanedUpMainContents);
var buildRequestData = new BuildRequestData(
mainProjectPath,
new Dictionary<string, string>(),
MSBuildConstants.CurrentToolsVersion,
new[] { "MainTarget" },
null);
var submission = _buildManager.PendBuildRequest(buildRequestData);
var result = submission.Execute();
var allEvents = _logger.AllBuildEvents;
if (isWarningExpected)
{
allEvents.OfType<T>().ShouldHaveSingleItem();
allEvents.First(x => x is T).Message.ShouldContain(
string.Format(ResourceUtilities.GetResourceString("DeprecatedEventSerialization"),
"MyCustomBuildEventArgs"));
}
else
{
allEvents.OfType<T>().ShouldBeEmpty();
}
}
finally
{
_buildManager.EndBuild();
}
}
private BuildParameters BuildParameters => new BuildParameters(_projectCollection)
{
DisableInProcNode = true,
EnableNodeReuse = false,
Loggers = new ILogger[] { _logger }
};
/// <summary>
/// TearDown
/// </summary>
public void Dispose()
{
_buildManager.Dispose();
_projectCollection.Dispose();
_env.Dispose();
}
}
}

Просмотреть файл

@ -0,0 +1,25 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
#nullable disable
namespace Microsoft.Build.UnitTests
{
public class CustomBuildEventTask : Task
{
public override bool Execute()
{
MyCustomBuildEventArgs customBuildEvent = new() { RawMessage = "A message from MyCustomBuildEventArgs" };
BuildEngine.LogCustomEvent(customBuildEvent);
return true;
}
[Serializable]
public sealed class MyCustomBuildEventArgs : CustomBuildEventArgs { }
}
}

Просмотреть файл

@ -5,6 +5,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Microsoft.Build.BackEnd;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
@ -57,8 +58,21 @@ namespace Microsoft.Build.UnitTests.BackEnd
ProjectStartedEventArgs projectStarted = new ProjectStartedEventArgs(-1, "message", "help", "ProjectFile", "targetNames", null, null, null);
ProjectFinishedEventArgs projectFinished = new ProjectFinishedEventArgs("message", "help", "ProjectFile", true);
ExternalProjectStartedEventArgs externalStartedEvent = new ExternalProjectStartedEventArgs("message", "help", "senderName", "projectFile", "targetNames");
ExternalProjectFinishedEventArgs externalFinishedEvent = new("message", "help", "senderName", "projectFile", true);
ProjectEvaluationStartedEventArgs evaluationStarted = new ProjectEvaluationStartedEventArgs();
ProjectEvaluationFinishedEventArgs evaluationFinished = new ProjectEvaluationFinishedEventArgs();
AssemblyLoadBuildEventArgs assemblyLoad = new(AssemblyLoadingContext.Evaluation, null, null, "path", Guid.NewGuid(), null);
ExtendedBuildErrorEventArgs extError = new("extError", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender");
ExtendedBuildWarningEventArgs extWarning = new("extWarn", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender");
ExtendedBuildMessageEventArgs extMessage = new("extMsg", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender", MessageImportance.Normal);
ExtendedCustomBuildEventArgs extCustom = new("extCustom", "message", "help", "sender");
CriticalBuildMessageEventArgs criticalMessage = new("Subcategory", "Code", "File", 1, 2, 3, 4, "{0}", "HelpKeyword", "Sender", DateTime.Now, "arg1");
PropertyInitialValueSetEventArgs propInit = new("prop", "val", "propsource", "message", "help", "sender", MessageImportance.Normal);
MetaprojectGeneratedEventArgs metaProjectGenerated = new("metaName", "path", "message");
PropertyReassignmentEventArgs propReassign = new("prop", "prevValue", "newValue", "loc", "message", "help", "sender", MessageImportance.Normal);
ResponseFileUsedEventArgs responseFileUsed = new("path");
UninitializedPropertyReadEventArgs uninitializedPropertyRead = new("prop", "message", "help", "sender", MessageImportance.Normal);
EnvironmentVariableReadEventArgs environmentVariableRead = new("env", "message", "help", "sender", MessageImportance.Normal);
VerifyLoggingPacket(buildFinished, LoggingEventType.BuildFinishedEvent);
VerifyLoggingPacket(buildStarted, LoggingEventType.BuildStartedEvent);
@ -76,7 +90,20 @@ namespace Microsoft.Build.UnitTests.BackEnd
VerifyLoggingPacket(projectFinished, LoggingEventType.ProjectFinishedEvent);
VerifyLoggingPacket(evaluationStarted, LoggingEventType.ProjectEvaluationStartedEvent);
VerifyLoggingPacket(evaluationFinished, LoggingEventType.ProjectEvaluationFinishedEvent);
VerifyLoggingPacket(externalStartedEvent, LoggingEventType.CustomEvent);
VerifyLoggingPacket(externalStartedEvent, LoggingEventType.ExternalProjectStartedEvent);
VerifyLoggingPacket(externalFinishedEvent, LoggingEventType.ExternalProjectFinishedEvent);
VerifyLoggingPacket(assemblyLoad, LoggingEventType.AssemblyLoadEvent);
VerifyLoggingPacket(extError, LoggingEventType.ExtendedBuildErrorEvent);
VerifyLoggingPacket(extWarning, LoggingEventType.ExtendedBuildWarningEvent);
VerifyLoggingPacket(extMessage, LoggingEventType.ExtendedBuildMessageEvent);
VerifyLoggingPacket(extCustom, LoggingEventType.ExtendedCustomEvent);
VerifyLoggingPacket(criticalMessage, LoggingEventType.CriticalBuildMessage);
VerifyLoggingPacket(propInit, LoggingEventType.PropertyInitialValueSet);
VerifyLoggingPacket(metaProjectGenerated, LoggingEventType.MetaprojectGenerated);
VerifyLoggingPacket(propReassign, LoggingEventType.PropertyReassignment);
VerifyLoggingPacket(responseFileUsed, LoggingEventType.ResponseFileUsedEvent);
VerifyLoggingPacket(uninitializedPropertyRead, LoggingEventType.UninitializedPropertyRead);
VerifyLoggingPacket(environmentVariableRead, LoggingEventType.EnvironmentVariableReadEvent);
}
private static BuildEventContext CreateBuildEventContext()
@ -218,6 +245,13 @@ namespace Microsoft.Build.UnitTests.BackEnd
{
BuildEventArgs[] testArgs = new BuildEventArgs[]
{
new ResponseFileUsedEventArgs("path"),
new UninitializedPropertyReadEventArgs("prop", "message", "help", "sender", MessageImportance.Normal),
new EnvironmentVariableReadEventArgs("env", "message", "help", "sender", MessageImportance.Normal) { BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6) },
new PropertyReassignmentEventArgs("prop", "prevValue", "newValue", "loc", "message", "help", "sender", MessageImportance.Normal),
new PropertyInitialValueSetEventArgs("prop", "val", "propsource", "message", "help", "sender", MessageImportance.Normal),
new MetaprojectGeneratedEventArgs("metaName", "path", "message"),
new CriticalBuildMessageEventArgs("Subcategory", "Code", "File", 1, 2, 3, 4, "{0}", "HelpKeyword", "Sender", DateTime.Now, "arg1"),
new BuildFinishedEventArgs("Message", "Keyword", true),
new BuildStartedEventArgs("Message", "Help"),
new BuildMessageEventArgs("Message", "help", "sender", MessageImportance.Low),
@ -236,11 +270,36 @@ namespace Microsoft.Build.UnitTests.BackEnd
new ProjectStartedEventArgs(-1, "message", "help", "ProjectFile", "targetNames", null, null, null),
new ProjectFinishedEventArgs("message", "help", "ProjectFile", true),
new ExternalProjectStartedEventArgs("message", "help", "senderName", "projectFile", "targetNames"),
new ExternalProjectFinishedEventArgs("message", "help", "senderName", "projectFile", true),
CreateProjectEvaluationStarted(),
CreateProjectEvaluationFinished(),
CreateTargetSkipped()
new AssemblyLoadBuildEventArgs(AssemblyLoadingContext.Evaluation, "init", "aname", "path", Guid.NewGuid(), "domain", MessageImportance.Normal),
CreateTargetSkipped(),
new ExtendedBuildErrorEventArgs("extError", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender", DateTime.UtcNow, "arg1")
{
ExtendedData = "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary<string, string> { { "m1", "v1" }, { "m2", "v2" } },
BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
},
new ExtendedBuildWarningEventArgs("extWarn", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender", DateTime.UtcNow, "arg1")
{
ExtendedData = "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary<string, string> { { "m1", "v1" }, { "m2", "v2" } },
BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
},
new ExtendedBuildMessageEventArgs("extWarn", "SubCategoryForSchemaValidationErrors", "MSB4000", "file", 1, 2, 3, 4, "message", "help", "sender", MessageImportance.Normal, DateTime.UtcNow, "arg1")
{
ExtendedData = "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary<string, string> { { "m1", "v1" }, { "m2", "v2" } },
BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
},
new ExtendedCustomBuildEventArgs("extCustom", "message", "help", "sender", DateTime.UtcNow, "arg1")
{
ExtendedData = "{'long-json':'mostly-strings'}",
ExtendedMetadata = new Dictionary<string, string> { { "m1", "v1" }, { "m2", "v2" } },
BuildEventContext = new BuildEventContext(1, 2, 3, 4, 5, 6, 7)
},
};
foreach (BuildEventArgs arg in testArgs)
{
LogMessagePacket packet = new LogMessagePacket(new KeyValuePair<int, BuildEventArgs>(0, arg));
@ -250,7 +309,17 @@ namespace Microsoft.Build.UnitTests.BackEnd
LogMessagePacket deserializedPacket = tempPacket as LogMessagePacket;
CompareLogMessagePackets(packet, deserializedPacket);
packet.Should().BeEquivalentTo(deserializedPacket, options => options
.RespectingRuntimeTypes());
BuildEventArgs args = packet.NodeBuildEvent?.Value;
BuildEventArgs desArgs = deserializedPacket?.NodeBuildEvent?.Value;
desArgs.Should().BeEquivalentTo(args, options => options
.RespectingRuntimeTypes()
// Since we use struct DictionaryEntry of class TaskItemData, generated DictionaryEntry.Equals compare TaskItemData by references.
// Bellow will instruct equivalency test to not use DictionaryEntry.Equals but its public members for equivalency tests.
.ComparingByMembers<DictionaryEntry>()
.WithTracing(), "Roundtrip deserialization of message type {0} should be equivalent", args.GetType().Name);
}
}
finally
@ -273,249 +342,6 @@ namespace Microsoft.Build.UnitTests.BackEnd
Assert.True(Object.ReferenceEquals(buildEvent, packet.NodeBuildEvent.Value.Value)); // "Expected buildEvent to have the same object reference as packet.BuildEvent"
}
/// <summary>
/// Compares two BuildEventArgs objects for equivalence.
/// </summary>
private void CompareNodeBuildEventArgs(KeyValuePair<int, BuildEventArgs> leftTuple, KeyValuePair<int, BuildEventArgs> rightTuple, bool expectInvalidBuildEventContext)
{
BuildEventArgs left = leftTuple.Value;
BuildEventArgs right = rightTuple.Value;
if (expectInvalidBuildEventContext)
{
Assert.Equal(BuildEventContext.Invalid, right.BuildEventContext);
}
else
{
Assert.Equal(left.BuildEventContext, right.BuildEventContext);
}
Assert.Equal(leftTuple.Key, rightTuple.Key);
Assert.Equal(left.HelpKeyword, right.HelpKeyword);
Assert.Equal(left.Message, right.Message);
Assert.Equal(left.SenderName, right.SenderName);
Assert.Equal(left.ThreadId, right.ThreadId);
Assert.Equal(left.Timestamp, right.Timestamp);
}
/// <summary>
/// Compares two LogMessagePacket objects for equivalence.
/// </summary>
private void CompareLogMessagePackets(LogMessagePacket left, LogMessagePacket right)
{
Assert.Equal(left.EventType, right.EventType);
Assert.Equal(left.NodeBuildEvent.Value.Value.GetType(), right.NodeBuildEvent.Value.Value.GetType());
CompareNodeBuildEventArgs(left.NodeBuildEvent.Value, right.NodeBuildEvent.Value, left.EventType == LoggingEventType.CustomEvent /* expectInvalidBuildEventContext */);
switch (left.EventType)
{
case LoggingEventType.BuildErrorEvent:
BuildErrorEventArgs leftError = left.NodeBuildEvent.Value.Value as BuildErrorEventArgs;
BuildErrorEventArgs rightError = right.NodeBuildEvent.Value.Value as BuildErrorEventArgs;
Assert.NotNull(leftError);
Assert.NotNull(rightError);
Assert.Equal(leftError.Code, rightError.Code);
Assert.Equal(leftError.ColumnNumber, rightError.ColumnNumber);
Assert.Equal(leftError.EndColumnNumber, rightError.EndColumnNumber);
Assert.Equal(leftError.EndLineNumber, rightError.EndLineNumber);
Assert.Equal(leftError.File, rightError.File);
Assert.Equal(leftError.LineNumber, rightError.LineNumber);
Assert.Equal(leftError.Message, rightError.Message);
Assert.Equal(leftError.Subcategory, rightError.Subcategory);
break;
case LoggingEventType.BuildFinishedEvent:
BuildFinishedEventArgs leftFinished = left.NodeBuildEvent.Value.Value as BuildFinishedEventArgs;
BuildFinishedEventArgs rightFinished = right.NodeBuildEvent.Value.Value as BuildFinishedEventArgs;
Assert.NotNull(leftFinished);
Assert.NotNull(rightFinished);
Assert.Equal(leftFinished.Succeeded, rightFinished.Succeeded);
break;
case LoggingEventType.BuildMessageEvent:
BuildMessageEventArgs leftMessage = left.NodeBuildEvent.Value.Value as BuildMessageEventArgs;
BuildMessageEventArgs rightMessage = right.NodeBuildEvent.Value.Value as BuildMessageEventArgs;
Assert.NotNull(leftMessage);
Assert.NotNull(rightMessage);
Assert.Equal(leftMessage.Importance, rightMessage.Importance);
break;
case LoggingEventType.BuildStartedEvent:
BuildStartedEventArgs leftBuildStart = left.NodeBuildEvent.Value.Value as BuildStartedEventArgs;
BuildStartedEventArgs rightBuildStart = right.NodeBuildEvent.Value.Value as BuildStartedEventArgs;
Assert.NotNull(leftBuildStart);
Assert.NotNull(rightBuildStart);
break;
case LoggingEventType.BuildWarningEvent:
BuildWarningEventArgs leftBuildWarn = left.NodeBuildEvent.Value.Value as BuildWarningEventArgs;
BuildWarningEventArgs rightBuildWarn = right.NodeBuildEvent.Value.Value as BuildWarningEventArgs;
Assert.NotNull(leftBuildWarn);
Assert.NotNull(rightBuildWarn);
Assert.Equal(leftBuildWarn.Code, rightBuildWarn.Code);
Assert.Equal(leftBuildWarn.ColumnNumber, rightBuildWarn.ColumnNumber);
Assert.Equal(leftBuildWarn.EndColumnNumber, rightBuildWarn.EndColumnNumber);
Assert.Equal(leftBuildWarn.EndLineNumber, rightBuildWarn.EndLineNumber);
Assert.Equal(leftBuildWarn.File, rightBuildWarn.File);
Assert.Equal(leftBuildWarn.LineNumber, rightBuildWarn.LineNumber);
Assert.Equal(leftBuildWarn.Subcategory, rightBuildWarn.Subcategory);
break;
case LoggingEventType.CustomEvent:
ExternalProjectStartedEventArgs leftCustom = left.NodeBuildEvent.Value.Value as ExternalProjectStartedEventArgs;
ExternalProjectStartedEventArgs rightCustom = right.NodeBuildEvent.Value.Value as ExternalProjectStartedEventArgs;
Assert.NotNull(leftCustom);
Assert.NotNull(rightCustom);
Assert.Equal(leftCustom.ProjectFile, rightCustom.ProjectFile);
Assert.Equal(leftCustom.TargetNames, rightCustom.TargetNames);
break;
case LoggingEventType.ProjectFinishedEvent:
ProjectFinishedEventArgs leftProjectFinished = left.NodeBuildEvent.Value.Value as ProjectFinishedEventArgs;
ProjectFinishedEventArgs rightProjectFinished = right.NodeBuildEvent.Value.Value as ProjectFinishedEventArgs;
Assert.NotNull(leftProjectFinished);
Assert.NotNull(rightProjectFinished);
Assert.Equal(leftProjectFinished.ProjectFile, rightProjectFinished.ProjectFile);
Assert.Equal(leftProjectFinished.Succeeded, rightProjectFinished.Succeeded);
break;
case LoggingEventType.ProjectStartedEvent:
ProjectStartedEventArgs leftProjectStarted = left.NodeBuildEvent.Value.Value as ProjectStartedEventArgs;
ProjectStartedEventArgs rightProjectStarted = right.NodeBuildEvent.Value.Value as ProjectStartedEventArgs;
Assert.NotNull(leftProjectStarted);
Assert.NotNull(rightProjectStarted);
Assert.Equal(leftProjectStarted.ParentProjectBuildEventContext, rightProjectStarted.ParentProjectBuildEventContext);
Assert.Equal(leftProjectStarted.ProjectFile, rightProjectStarted.ProjectFile);
Assert.Equal(leftProjectStarted.ProjectId, rightProjectStarted.ProjectId);
Assert.Equal(leftProjectStarted.TargetNames, rightProjectStarted.TargetNames);
// UNDONE: (Serialization.) We don't actually serialize the items at this time.
// Assert.AreEqual(leftProjectStarted.Items, rightProjectStarted.Items);
// UNDONE: (Serialization.) We don't actually serialize properties at this time.
// Assert.AreEqual(leftProjectStarted.Properties, rightProjectStarted.Properties);
break;
case LoggingEventType.ProjectEvaluationStartedEvent:
ProjectEvaluationStartedEventArgs leftEvaluationStarted = left.NodeBuildEvent.Value.Value as ProjectEvaluationStartedEventArgs;
ProjectEvaluationStartedEventArgs rightEvaluationStarted = right.NodeBuildEvent.Value.Value as ProjectEvaluationStartedEventArgs;
Assert.NotNull(leftEvaluationStarted);
Assert.NotNull(rightEvaluationStarted);
Assert.Equal(leftEvaluationStarted.ProjectFile, rightEvaluationStarted.ProjectFile);
break;
case LoggingEventType.ProjectEvaluationFinishedEvent:
ProjectEvaluationFinishedEventArgs leftEvaluationFinished = left.NodeBuildEvent.Value.Value as ProjectEvaluationFinishedEventArgs;
ProjectEvaluationFinishedEventArgs rightEvaluationFinished = right.NodeBuildEvent.Value.Value as ProjectEvaluationFinishedEventArgs;
Assert.NotNull(leftEvaluationFinished);
Assert.NotNull(rightEvaluationFinished);
Assert.Equal(leftEvaluationFinished.ProjectFile, rightEvaluationFinished.ProjectFile);
Assert.Equal(leftEvaluationFinished.ProfilerResult, rightEvaluationFinished.ProfilerResult);
Assert.Equal(
TranslationHelpers.GetPropertiesString(leftEvaluationFinished.GlobalProperties),
TranslationHelpers.GetPropertiesString(rightEvaluationFinished.GlobalProperties));
Assert.Equal(
TranslationHelpers.GetPropertiesString(leftEvaluationFinished.Properties),
TranslationHelpers.GetPropertiesString(rightEvaluationFinished.Properties));
Assert.Equal(
TranslationHelpers.GetMultiItemsString(leftEvaluationFinished.Items),
TranslationHelpers.GetMultiItemsString(rightEvaluationFinished.Items));
break;
case LoggingEventType.TargetFinishedEvent:
TargetFinishedEventArgs leftTargetFinished = left.NodeBuildEvent.Value.Value as TargetFinishedEventArgs;
TargetFinishedEventArgs rightTargetFinished = right.NodeBuildEvent.Value.Value as TargetFinishedEventArgs;
Assert.NotNull(leftTargetFinished);
Assert.NotNull(rightTargetFinished);
Assert.Equal(leftTargetFinished.ProjectFile, rightTargetFinished.ProjectFile);
Assert.Equal(leftTargetFinished.Succeeded, rightTargetFinished.Succeeded);
Assert.Equal(leftTargetFinished.TargetFile, rightTargetFinished.TargetFile);
Assert.Equal(leftTargetFinished.TargetName, rightTargetFinished.TargetName);
// TODO: target output translation is a special case and is done in TranslateTargetFinishedEvent
// Assert.Equal(leftTargetFinished.TargetOutputs, rightTargetFinished.TargetOutputs);
break;
case LoggingEventType.TargetStartedEvent:
TargetStartedEventArgs leftTargetStarted = left.NodeBuildEvent.Value.Value as TargetStartedEventArgs;
TargetStartedEventArgs rightTargetStarted = right.NodeBuildEvent.Value.Value as TargetStartedEventArgs;
Assert.NotNull(leftTargetStarted);
Assert.NotNull(rightTargetStarted);
Assert.Equal(leftTargetStarted.ProjectFile, rightTargetStarted.ProjectFile);
Assert.Equal(leftTargetStarted.TargetFile, rightTargetStarted.TargetFile);
Assert.Equal(leftTargetStarted.TargetName, rightTargetStarted.TargetName);
break;
case LoggingEventType.TargetSkipped:
TargetSkippedEventArgs leftTargetSkipped = left.NodeBuildEvent.Value.Value as TargetSkippedEventArgs;
TargetSkippedEventArgs rightTargetSkipped = right.NodeBuildEvent.Value.Value as TargetSkippedEventArgs;
Assert.Equal(leftTargetSkipped.BuildReason, rightTargetSkipped.BuildReason);
Assert.Equal(leftTargetSkipped.SkipReason, rightTargetSkipped.SkipReason);
Assert.Equal(leftTargetSkipped.BuildEventContext, rightTargetSkipped.BuildEventContext);
Assert.Equal(leftTargetSkipped.OriginalBuildEventContext, rightTargetSkipped.OriginalBuildEventContext);
Assert.Equal(leftTargetSkipped.Condition, rightTargetSkipped.Condition);
Assert.Equal(leftTargetSkipped.EvaluatedCondition, rightTargetSkipped.EvaluatedCondition);
Assert.Equal(leftTargetSkipped.Importance, rightTargetSkipped.Importance);
Assert.Equal(leftTargetSkipped.OriginallySucceeded, rightTargetSkipped.OriginallySucceeded);
Assert.Equal(leftTargetSkipped.ProjectFile, rightTargetSkipped.ProjectFile);
Assert.Equal(leftTargetSkipped.TargetFile, rightTargetSkipped.TargetFile);
Assert.Equal(leftTargetSkipped.TargetName, rightTargetSkipped.TargetName);
Assert.Equal(leftTargetSkipped.ParentTarget, rightTargetSkipped.ParentTarget);
break;
case LoggingEventType.TaskCommandLineEvent:
TaskCommandLineEventArgs leftCommand = left.NodeBuildEvent.Value.Value as TaskCommandLineEventArgs;
TaskCommandLineEventArgs rightCommand = right.NodeBuildEvent.Value.Value as TaskCommandLineEventArgs;
Assert.NotNull(leftCommand);
Assert.NotNull(rightCommand);
Assert.Equal(leftCommand.CommandLine, rightCommand.CommandLine);
Assert.Equal(leftCommand.Importance, rightCommand.Importance);
Assert.Equal(leftCommand.TaskName, rightCommand.TaskName);
break;
case LoggingEventType.TaskParameterEvent:
var leftTaskParameter = left.NodeBuildEvent.Value.Value as TaskParameterEventArgs;
var rightTaskParameter = right.NodeBuildEvent.Value.Value as TaskParameterEventArgs;
Assert.NotNull(leftTaskParameter);
Assert.NotNull(rightTaskParameter);
Assert.Equal(leftTaskParameter.Kind, rightTaskParameter.Kind);
Assert.Equal(leftTaskParameter.ItemType, rightTaskParameter.ItemType);
Assert.Equal(leftTaskParameter.Items.Count, rightTaskParameter.Items.Count);
Assert.Equal(leftTaskParameter.Message, rightTaskParameter.Message);
Assert.Equal(leftTaskParameter.BuildEventContext, rightTaskParameter.BuildEventContext);
Assert.Equal(leftTaskParameter.Timestamp, rightTaskParameter.Timestamp);
Assert.Equal(leftTaskParameter.LineNumber, rightTaskParameter.LineNumber);
Assert.Equal(leftTaskParameter.ColumnNumber, rightTaskParameter.ColumnNumber);
break;
case LoggingEventType.TaskFinishedEvent:
TaskFinishedEventArgs leftTaskFinished = left.NodeBuildEvent.Value.Value as TaskFinishedEventArgs;
TaskFinishedEventArgs rightTaskFinished = right.NodeBuildEvent.Value.Value as TaskFinishedEventArgs;
Assert.NotNull(leftTaskFinished);
Assert.NotNull(rightTaskFinished);
Assert.Equal(leftTaskFinished.ProjectFile, rightTaskFinished.ProjectFile);
Assert.Equal(leftTaskFinished.Succeeded, rightTaskFinished.Succeeded);
Assert.Equal(leftTaskFinished.TaskFile, rightTaskFinished.TaskFile);
Assert.Equal(leftTaskFinished.TaskName, rightTaskFinished.TaskName);
break;
case LoggingEventType.TaskStartedEvent:
TaskStartedEventArgs leftTaskStarted = left.NodeBuildEvent.Value.Value as TaskStartedEventArgs;
TaskStartedEventArgs rightTaskStarted = right.NodeBuildEvent.Value.Value as TaskStartedEventArgs;
Assert.NotNull(leftTaskStarted);
Assert.NotNull(rightTaskStarted);
Assert.Equal(leftTaskStarted.ProjectFile, rightTaskStarted.ProjectFile);
Assert.Equal(leftTaskStarted.TaskFile, rightTaskStarted.TaskFile);
Assert.Equal(leftTaskStarted.TaskName, rightTaskStarted.TaskName);
Assert.Equal(leftTaskStarted.LineNumber, rightTaskStarted.LineNumber);
Assert.Equal(leftTaskStarted.ColumnNumber, rightTaskStarted.ColumnNumber);
break;
default:
Assert.True(false, string.Format("Unexpected logging event type {0}", left.EventType));
break;
}
}
#endregion
}
}

Просмотреть файл

@ -385,6 +385,61 @@ namespace Microsoft.Build.UnitTests.BackEnd
Assert.Equal("testCustomBuildEvent", _customLogger.LastCustom.Message);
}
/// <summary>
/// Test that extended custom events are logged properly
/// </summary>
[Fact]
public void TestLogExtendedCustomEventNotSerializableMP()
{
_mockHost.BuildParameters.MaxNodeCount = 4;
// Log the custom event args. (Pretend that the task actually did this.)
_taskHost.LogCustomEvent(new ExtendedCustomBuildEventArgs("testExtCustomBuildEvent", "ext message", null, null));
// Make sure our custom logger received the actual custom event and not some fake.
Assert.True(_customLogger.LastCustom is ExtendedCustomBuildEventArgs); // "Expected custom build Event"
Assert.Equal("ext message", _customLogger.LastCustom.Message);
}
[Fact]
public void TestLogExtendedCustomErrorNotSerializableMP()
{
_mockHost.BuildParameters.MaxNodeCount = 4;
// Log the custom event args. (Pretend that the task actually did this.)
_taskHost.LogErrorEvent(new ExtendedBuildErrorEventArgs("testExtCustomBuildError", null, null, null, 0, 0, 0, 0,"ext err message", null, null));
// Make sure our custom logger received the actual custom event and not some fake.
Assert.True(_customLogger.LastError is ExtendedBuildErrorEventArgs); // "Expected custom build Event"
Assert.Equal("ext err message", _customLogger.LastError.Message);
}
[Fact]
public void TestLogExtendedCustomWarningNotSerializableMP()
{
_mockHost.BuildParameters.MaxNodeCount = 4;
// Log the custom event args. (Pretend that the task actually did this.)
_taskHost.LogWarningEvent(new ExtendedBuildWarningEventArgs("testExtCustomBuildWarning", null, null, null, 0, 0, 0, 0, "ext warn message", null, null));
// Make sure our custom logger received the actual custom event and not some fake.
Assert.True(_customLogger.LastWarning is ExtendedBuildWarningEventArgs); // "Expected custom build Event"
Assert.Equal("ext warn message", _customLogger.LastWarning.Message);
}
[Fact]
public void TestLogExtendedCustomMessageNotSerializableMP()
{
_mockHost.BuildParameters.MaxNodeCount = 4;
// Log the custom event args. (Pretend that the task actually did this.)
_taskHost.LogMessageEvent(new ExtendedBuildMessageEventArgs("testExtCustomBuildMessage", "ext message", null, null, MessageImportance.Normal));
// Make sure our custom logger received the actual custom event and not some fake.
Assert.True(_customLogger.LastMessage is ExtendedBuildMessageEventArgs); // "Expected custom build Event"
Assert.Equal("ext message", _customLogger.LastMessage.Message);
}
/// <summary>
/// Test that errors are logged properly
/// </summary>

Просмотреть файл

@ -13,6 +13,7 @@ using Microsoft.Build.Framework.Profiler;
using Microsoft.Build.Logging;
using Microsoft.Build.Shared;
using Microsoft.Build.UnitTests.BackEnd;
using Shouldly;
using Xunit;
#nullable disable
@ -262,6 +263,40 @@ namespace Microsoft.Build.UnitTests
e => string.Join(", ", e.RawArguments ?? Array.Empty<object>()));
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void RoundtripExtendedErrorEventArgs_SerializedAsError(bool useArguments)
{
var args = new ExtendedBuildErrorEventArgs(
"extendedDataType",
"Subcategory",
"Code",
"File",
1,
2,
3,
4,
"Message with arguments: '{0}'",
"Help",
"SenderName",
DateTime.Parse("9/1/2021 12:02:07 PM"),
useArguments ? new object[] { "argument0" } : null);
// For now we don't serialize extended data into binary log
Roundtrip<BuildErrorEventArgs>(args,
e => e.Code,
e => e.ColumnNumber.ToString(),
e => e.EndColumnNumber.ToString(),
e => e.EndLineNumber.ToString(),
e => e.File,
e => e.LineNumber.ToString(),
e => e.Message,
e => e.ProjectFile,
e => e.Subcategory,
e => string.Join(", ", e.RawArguments ?? Array.Empty<object>()));
}
[Theory]
[InlineData(true)]
[InlineData(false)]
@ -294,6 +329,40 @@ namespace Microsoft.Build.UnitTests
e => string.Join(", ", e.RawArguments ?? Array.Empty<object>()));
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void RoundtripExtendedWarningEventArgs_SerializedAsWarning(bool useArguments)
{
var args = new ExtendedBuildWarningEventArgs(
"extendedDataType",
"Subcategory",
"Code",
"File",
1,
2,
3,
4,
"Message with arguments: '{0}'",
"Help",
"SenderName",
DateTime.Parse("9/1/2021 12:02:07 PM"),
useArguments ? new object[] { "argument0" } : null);
// For now we don't serialize extended data into binary log
Roundtrip<BuildWarningEventArgs>(args,
e => e.Code,
e => e.ColumnNumber.ToString(),
e => e.EndColumnNumber.ToString(),
e => e.EndLineNumber.ToString(),
e => e.File,
e => e.LineNumber.ToString(),
e => e.Message,
e => e.ProjectFile,
e => e.Subcategory,
e => string.Join(", ", e.RawArguments ?? Array.Empty<object>()));
}
[Theory]
[InlineData(true)]
[InlineData(false)]
@ -328,6 +397,122 @@ namespace Microsoft.Build.UnitTests
e => string.Join(", ", e.RawArguments ?? Array.Empty<object>()));
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void RoundtripExtendedBuildMessageEventArgs_SerializedAsMessage(bool useArguments)
{
var args = new ExtendedBuildMessageEventArgs(
"extendedDataType",
"Subcategory",
"Code",
"File",
1,
2,
3,
4,
"Message",
"Help",
"SenderName",
MessageImportance.High,
DateTime.Parse("12/12/2015 06:11:56 PM"),
useArguments ? new object[] { "argument0" } : null);
Roundtrip<BuildMessageEventArgs>(args,
e => e.Code,
e => e.ColumnNumber.ToString(),
e => e.EndColumnNumber.ToString(),
e => e.EndLineNumber.ToString(),
e => e.File,
e => e.LineNumber.ToString(),
e => e.Message,
e => e.Importance.ToString(),
e => e.ProjectFile,
e => e.Subcategory,
e => string.Join(", ", e.RawArguments ?? Array.Empty<object>()));
}
[Fact]
public void RoundtripAssemblyLoadBuild()
{
string assemblyName = Guid.NewGuid().ToString();
string assemblyPath = Guid.NewGuid().ToString();
Guid mvid = Guid.NewGuid();
string loadingInitiator = Guid.NewGuid().ToString();
string appDomainName = Guid.NewGuid().ToString();
AssemblyLoadingContext context =
(AssemblyLoadingContext)(new Random().Next(Enum.GetNames(typeof(AssemblyLoadingContext)).Length));
AssemblyLoadBuildEventArgs args = new(context, loadingInitiator, assemblyName, assemblyPath, mvid, appDomainName);
Roundtrip(args,
e => e.Code,
e => e.ColumnNumber.ToString(),
e => e.EndColumnNumber.ToString(),
e => e.EndLineNumber.ToString(),
e => e.File,
e => e.LineNumber.ToString(),
e => e.Message,
e => e.Importance.ToString(),
e => e.ProjectFile,
e => e.Subcategory,
e => e.LoadingContext.ToString(),
e => e.AssemblyName,
e => e.AssemblyPath,
e => e.MVID.ToString(),
e => e.AppDomainDescriptor,
e => string.Join(", ", e.RawArguments ?? Array.Empty<object>()));
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void ExtendedCustomBuildEventArgs_SerializedAsMessage(bool withOptionalData)
{
ExtendedCustomBuildEventArgs args = new(
type: "TypeOfExtendedCustom",
message: withOptionalData ? "a message with args {0} {1}" : null,
helpKeyword: withOptionalData ? "MSBT123" : null,
senderName: withOptionalData ? $"UnitTest {Guid.NewGuid()}" : null,
eventTimestamp: withOptionalData ? DateTime.Parse("3/1/2017 11:11:56 AM") : DateTime.Now,
messageArgs: withOptionalData ? new object[] { "arg0val", "arg1val" } : null)
{
ExtendedData = withOptionalData ? "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary<string, string> { { "m1", "v1" }, { "m2", "v2" } } : null,
BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
};
var memoryStream = new MemoryStream();
var binaryWriter = new BinaryWriter(memoryStream);
var buildEventArgsWriter = new BuildEventArgsWriter(binaryWriter);
buildEventArgsWriter.Write(args);
memoryStream.Position = 0;
var binaryReader = new BinaryReader(memoryStream);
using var buildEventArgsReader = new BuildEventArgsReader(binaryReader, BinaryLogger.FileFormatVersion);
var deserialized = buildEventArgsReader.Read();
BuildMessageEventArgs desArgs = (BuildMessageEventArgs)deserialized;
desArgs.ShouldBeOfType(typeof(BuildMessageEventArgs));
desArgs.Message.ShouldBe(args.Message);
desArgs.HelpKeyword.ShouldBe(args.HelpKeyword);
desArgs.SenderName.ShouldBe(args.SenderName);
desArgs.Importance.ShouldBe(MessageImportance.Normal);
desArgs.Timestamp.ShouldBe(args.Timestamp);
if (withOptionalData)
{
desArgs.BuildEventContext.ShouldBe(args.BuildEventContext);
}
else
{
desArgs.BuildEventContext.ShouldBe(BuildEventContext.Invalid);
}
}
[Fact]
public void RoundtripResponseFileUsedEventArgs()
{
@ -689,7 +874,7 @@ namespace Microsoft.Build.UnitTests
Assert.Equal(length, memoryStream.Position);
Assert.NotNull(deserializedArgs);
Assert.Equal(args.GetType(), deserializedArgs.GetType());
Assert.Equal(typeof(T), deserializedArgs.GetType());
foreach (var field in fieldsToCompare)
{

Просмотреть файл

@ -16,7 +16,7 @@
<ItemGroup>
<Reference Include="System.IO.Compression" Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'" />
<PackageReference Include="FluentAssertions" />
<PackageReference Include="System.Configuration.ConfigurationManager" />
<PackageReference Include="Shouldly" />
<PackageReference Include="System.Net.Http" />

Просмотреть файл

@ -31,7 +31,7 @@ namespace Microsoft.Build.BackEnd
/// Constructor for deserialization
/// </summary>
private LogMessagePacket(ITranslator translator)
: base(translator)
: base(translator, new TargetFinishedTranslator(TranslateTargetFinishedEvent))
{
}

Просмотреть файл

@ -901,9 +901,60 @@ namespace Microsoft.Build.BackEnd.Logging
LogMessagePacket loggingPacket = (LogMessagePacket)packet;
InjectNonSerializedData(loggingPacket);
WarnOnDeprecatedCustomArgsSerialization(loggingPacket);
ProcessLoggingEvent(loggingPacket.NodeBuildEvent);
}
/// <summary>
/// Serializing unknown CustomEvent which has to use unsecure BinaryFormatter by TranslateDotNet.
/// Since BinaryFormatter is going to be deprecated, log warning so users can use new Extended*EventArgs instead of custom
/// EventArgs derived from existing EventArgs.
/// </summary>
private void WarnOnDeprecatedCustomArgsSerialization(LogMessagePacket loggingPacket)
{
if (loggingPacket.EventType == LoggingEventType.CustomEvent
&& ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_8)
&& Traits.Instance.EscapeHatches.EnableWarningOnCustomBuildEvent)
{
BuildEventArgs buildEvent = loggingPacket.NodeBuildEvent.Value.Value;
BuildEventContext buildEventContext = buildEvent?.BuildEventContext ?? BuildEventContext.Invalid;
string message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword(
out string warningCode,
out string helpKeyword,
"DeprecatedEventSerialization",
buildEvent?.GetType().Name ?? string.Empty);
BuildWarningEventArgs warning = new(
null,
warningCode,
BuildEventFileInfo.Empty.File,
BuildEventFileInfo.Empty.Line,
BuildEventFileInfo.Empty.Column,
BuildEventFileInfo.Empty.EndLine,
BuildEventFileInfo.Empty.EndColumn,
message,
helpKeyword,
"MSBuild");
warning.BuildEventContext = buildEventContext;
if (warning.ProjectFile == null && buildEventContext.ProjectContextId != BuildEventContext.InvalidProjectContextId)
{
warning.ProjectFile = buildEvent switch
{
BuildMessageEventArgs buildMessageEvent => buildMessageEvent.ProjectFile,
BuildErrorEventArgs buildErrorEvent => buildErrorEvent.ProjectFile,
BuildWarningEventArgs buildWarningEvent => buildWarningEvent.ProjectFile,
_ => null,
};
}
ProcessLoggingEvent(warning);
}
}
/// <summary>
/// Register an instantiated logger which implements the ILogger interface. This logger will be registered to a specific event
/// source (the central logger event source) which will receive all logging messages for a given build.
@ -1438,42 +1489,93 @@ namespace Microsoft.Build.BackEnd.Logging
{
if (ShouldTreatWarningAsMessage(warningEvent))
{
buildEventArgs = new BuildMessageEventArgs(
warningEvent.Subcategory,
warningEvent.Code,
warningEvent.File,
warningEvent.LineNumber,
warningEvent.ColumnNumber,
warningEvent.EndLineNumber,
warningEvent.EndColumnNumber,
warningEvent.Message,
warningEvent.HelpKeyword,
warningEvent.SenderName,
MessageImportance.Low,
warningEvent.Timestamp)
if (buildEventArgs is ExtendedBuildWarningEventArgs extWarningEvent)
{
BuildEventContext = warningEvent.BuildEventContext,
ProjectFile = warningEvent.ProjectFile,
};
buildEventArgs = new ExtendedBuildMessageEventArgs(
extWarningEvent.ExtendedType,
extWarningEvent.Subcategory,
extWarningEvent.Code,
extWarningEvent.File,
extWarningEvent.LineNumber,
extWarningEvent.ColumnNumber,
extWarningEvent.EndLineNumber,
extWarningEvent.EndColumnNumber,
extWarningEvent.Message,
extWarningEvent.HelpKeyword,
extWarningEvent.SenderName,
MessageImportance.Low,
extWarningEvent.Timestamp)
{
BuildEventContext = warningEvent.BuildEventContext,
ProjectFile = warningEvent.ProjectFile,
ExtendedMetadata = extWarningEvent.ExtendedMetadata,
ExtendedData = extWarningEvent.ExtendedData,
};
}
else
{
buildEventArgs = new BuildMessageEventArgs(
warningEvent.Subcategory,
warningEvent.Code,
warningEvent.File,
warningEvent.LineNumber,
warningEvent.ColumnNumber,
warningEvent.EndLineNumber,
warningEvent.EndColumnNumber,
warningEvent.Message,
warningEvent.HelpKeyword,
warningEvent.SenderName,
MessageImportance.Low,
warningEvent.Timestamp)
{
BuildEventContext = warningEvent.BuildEventContext,
ProjectFile = warningEvent.ProjectFile,
};
}
}
else if (ShouldTreatWarningAsError(warningEvent))
{
buildEventArgs = new BuildErrorEventArgs(
warningEvent.Subcategory,
warningEvent.Code,
warningEvent.File,
warningEvent.LineNumber,
warningEvent.ColumnNumber,
warningEvent.EndLineNumber,
warningEvent.EndColumnNumber,
warningEvent.Message,
warningEvent.HelpKeyword,
warningEvent.SenderName,
warningEvent.Timestamp)
if (warningEvent is ExtendedBuildWarningEventArgs extWarningEvent)
{
BuildEventContext = warningEvent.BuildEventContext,
ProjectFile = warningEvent.ProjectFile,
};
buildEventArgs = new ExtendedBuildErrorEventArgs(
extWarningEvent.ExtendedType,
extWarningEvent.Subcategory,
extWarningEvent.Code,
extWarningEvent.File,
extWarningEvent.LineNumber,
extWarningEvent.ColumnNumber,
extWarningEvent.EndLineNumber,
extWarningEvent.EndColumnNumber,
extWarningEvent.Message,
extWarningEvent.HelpKeyword,
extWarningEvent.SenderName,
extWarningEvent.Timestamp)
{
BuildEventContext = warningEvent.BuildEventContext,
ProjectFile = warningEvent.ProjectFile,
ExtendedMetadata = extWarningEvent.ExtendedMetadata,
ExtendedData = extWarningEvent.ExtendedData,
};
}
else
{
buildEventArgs = new BuildErrorEventArgs(
warningEvent.Subcategory,
warningEvent.Code,
warningEvent.File,
warningEvent.LineNumber,
warningEvent.ColumnNumber,
warningEvent.EndLineNumber,
warningEvent.EndColumnNumber,
warningEvent.Message,
warningEvent.HelpKeyword,
warningEvent.SenderName,
warningEvent.Timestamp)
{
BuildEventContext = warningEvent.BuildEventContext,
ProjectFile = warningEvent.ProjectFile,
};
}
}
}

Просмотреть файл

@ -1080,7 +1080,9 @@ namespace Microsoft.Build.BackEnd
internal bool IsEventSerializable(BuildEventArgs e)
{
#pragma warning disable SYSLIB0050
if (!e.GetType().GetTypeInfo().IsSerializable)
// Types which are not serializable and are not IExtendedBuildEventArgs as
// those always implement custom serialization by WriteToStream and CreateFromStream.
if (!e.GetType().GetTypeInfo().IsSerializable && e is not IExtendedBuildEventArgs)
#pragma warning restore SYSLIB0050
{
_taskLoggingContext.LogWarning(null, new BuildEventFileInfo(string.Empty), "ExpectedEventToBeSerializable", e.GetType().Name);

Просмотреть файл

@ -572,7 +572,28 @@ namespace Microsoft.Build.Execution
{
if (_nodeEndpoint.LinkStatus == LinkStatus.Active)
{
#if RUNTIME_TYPE_NETCORE
if (packet is LogMessagePacketBase logMessage
&& logMessage.EventType == LoggingEventType.CustomEvent
&& ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_8)
&& Traits.Instance.EscapeHatches.EnableWarningOnCustomBuildEvent)
{
BuildEventArgs buildEvent = logMessage.NodeBuildEvent.Value.Value;
// Serializing unknown CustomEvent which has to use unsecure BinaryFormatter by TranslateDotNet<T>
// Since BinaryFormatter is deprecated in dotnet 8+, log error so users discover root cause easier
// then by reading CommTrace where it would be otherwise logged as critical infra error.
_loggingService.LogError(_loggingContext?.BuildEventContext ?? BuildEventContext.Invalid, null, BuildEventFileInfo.Empty,
"DeprecatedEventSerialization",
buildEvent?.GetType().Name ?? string.Empty);
}
else
{
_nodeEndpoint.SendData(packet);
}
#else
_nodeEndpoint.SendData(packet);
#endif
}
}

Просмотреть файл

@ -338,7 +338,9 @@ namespace Microsoft.Build.BackEnd
internal bool IsEventSerializable(BuildEventArgs e)
{
#pragma warning disable SYSLIB0050
if (!e.GetType().GetTypeInfo().IsSerializable)
// Types which are not serializable and are not IExtendedBuildEventArgs as
// those always implement custom serialization by WriteToStream and CreateFromStream.
if (!e.GetType().GetTypeInfo().IsSerializable && e is not IExtendedBuildEventArgs)
#pragma warning restore SYSLIB0050
{
_loggingContext.LogWarning(null, new BuildEventFileInfo(string.Empty), "ExpectedEventToBeSerializable", e.GetType().Name);

Просмотреть файл

@ -156,6 +156,7 @@ namespace Microsoft.Build.Logging
TaskCommandLine
TaskParameter
UninitializedPropertyRead
ExtendedMessage
BuildStatus
TaskStarted
TaskFinished
@ -168,11 +169,13 @@ namespace Microsoft.Build.Logging
ProjectEvaluationStarted
ProjectEvaluationFinished
BuildError
ExtendedBuildError
BuildWarning
ExtendedBuildWarning
CustomBuild
ExternalProjectStarted
ExternalProjectFinished
ExtendedCustomBuild
*/
private void WriteCore(BuildEventArgs e)

Просмотреть файл

@ -31,7 +31,6 @@ namespace Microsoft.Build.Framework.UnitTests
AssemblyLoadBuildEventArgs argDeserialized = new();
int packetVersion = (Environment.Version.Major * 10) + Environment.Version.Minor;
argDeserialized.CreateFromStream(br, packetVersion);
argDeserialized.LoadingInitiator.ShouldBe(loadingInitiator);
argDeserialized.AssemblyName.ShouldBe(assemblyName);
argDeserialized.AssemblyPath.ShouldBe(assemblyPath);

Просмотреть файл

@ -0,0 +1,218 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.IO;
using FluentAssertions;
using Xunit;
namespace Microsoft.Build.Framework.UnitTests;
public class ExtendedBuildEventArgs_Tests
{
[InlineData(true)]
[InlineData(false)]
[Theory]
public void ExtendedCustomBuildEventArgs_SerializationDeserialization(bool withOptionalData)
{
ExtendedCustomBuildEventArgs arg = new(
type: "TypeOfExtendedCustom",
message: withOptionalData ? "a message with args {0} {1}" : null,
helpKeyword: withOptionalData ? "MSBT123" : null,
senderName: withOptionalData ? $"UnitTest {Guid.NewGuid()}" : null,
eventTimestamp: withOptionalData ? DateTime.Parse("3/1/2017 11:11:56 AM") : DateTime.Now,
messageArgs: withOptionalData ? new object[] { "arg0val", "arg1val" } : null)
{
ExtendedData = withOptionalData ? "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary<string, string?> { {"m1", "v1" }, { "m2", "v2" } } : null,
BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
};
using MemoryStream stream = new MemoryStream();
using BinaryWriter bw = new BinaryWriter(stream);
arg.WriteToStream(bw);
stream.Position = 0;
using BinaryReader br = new BinaryReader(stream);
ExtendedCustomBuildEventArgs argDeserialized = new();
argDeserialized.CreateFromStream(br, 80);
argDeserialized.Should().BeEquivalentTo(arg);
}
[InlineData(true)]
[InlineData(false)]
[Theory]
public void ExtendedErrorEventArgs_SerializationDeserialization(bool withOptionalData)
{
ExtendedBuildErrorEventArgs arg = new(
type: "TypeOfExtendedCustom",
subcategory: withOptionalData ? "sub-type" : null,
code: withOptionalData ? "a-code" : null,
file: withOptionalData ? ".\\dev\\my.csproj" : null,
lineNumber: withOptionalData ? 1 : default,
columnNumber: withOptionalData ? 2 : default,
endLineNumber: withOptionalData ? 3 : default,
endColumnNumber: withOptionalData ? 4 : default,
message: withOptionalData ? "a message with args {0} {1}" : null,
helpKeyword: withOptionalData ? "MSBT123" : null,
senderName: withOptionalData ? $"UnitTest {Guid.NewGuid()}" : null,
helpLink: withOptionalData ? "(001)2234456" : null,
eventTimestamp: withOptionalData ? DateTime.Parse("3/1/2017 11:11:56 AM") : DateTime.Now,
messageArgs: withOptionalData ? new object[] { "arg0val", "arg1val" } : null)
{
ExtendedData = withOptionalData ? "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary<string, string?> { { "m1", "v1" }, { "m2", "v2" } } : null,
BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
};
using MemoryStream stream = new MemoryStream();
using BinaryWriter bw = new BinaryWriter(stream);
arg.WriteToStream(bw);
stream.Position = 0;
using BinaryReader br = new BinaryReader(stream);
ExtendedBuildErrorEventArgs argDeserialized = new();
argDeserialized.CreateFromStream(br, 80);
argDeserialized.Should().BeEquivalentTo(arg);
}
[InlineData(true)]
[InlineData(false)]
[Theory]
public void ExtendedWarningEventArgs_SerializationDeserialization(bool withOptionalData)
{
ExtendedBuildWarningEventArgs arg = new(
type: "TypeOfExtendedCustom",
subcategory: withOptionalData ? "sub-type" : null,
code: withOptionalData ? "a-code" : null,
file: withOptionalData ? ".\\dev\\my.csproj" : null,
lineNumber: withOptionalData ? 1 : default,
columnNumber: withOptionalData ? 2 : default,
endLineNumber: withOptionalData ? 3 : default,
endColumnNumber: withOptionalData ? 4 : default,
message: withOptionalData ? "a message with args {0} {1}" : null,
helpKeyword: withOptionalData ? "MSBT123" : null,
senderName: withOptionalData ? $"UnitTest {Guid.NewGuid()}" : null,
helpLink: withOptionalData ? "(001)2234456" : null,
eventTimestamp: withOptionalData ? DateTime.Parse("3/1/2017 11:11:56 AM") : DateTime.Now,
messageArgs: withOptionalData ? new object[] { "arg0val", "arg1val" } : null)
{
ExtendedData = withOptionalData ? "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary<string, string?> { { "m1", "v1" }, { "m2", "v2" } } : null,
BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
};
using MemoryStream stream = new MemoryStream();
using BinaryWriter bw = new BinaryWriter(stream);
arg.WriteToStream(bw);
stream.Position = 0;
using BinaryReader br = new BinaryReader(stream);
ExtendedBuildWarningEventArgs argDeserialized = new();
argDeserialized.CreateFromStream(br, 80);
argDeserialized.Should().BeEquivalentTo(arg);
}
[InlineData(true)]
[InlineData(false)]
[Theory]
public void ExtendedMessageEventArgs_SerializationDeserialization(bool withOptionalData)
{
ExtendedBuildMessageEventArgs arg = new(
type: "TypeOfExtendedCustom",
subcategory: withOptionalData ? "sub-type" : null,
code: withOptionalData ? "a-code" : null,
file: withOptionalData ? ".\\dev\\my.csproj" : null,
lineNumber: withOptionalData ? 1 : default,
columnNumber: withOptionalData ? 2 : default,
endLineNumber: withOptionalData ? 3 : default,
endColumnNumber: withOptionalData ? 4 : default,
message: withOptionalData ? "a message with args {0} {1}" : null,
helpKeyword: withOptionalData ? "MSBT123" : null,
senderName: withOptionalData ? $"UnitTest {Guid.NewGuid()}" : null,
importance: withOptionalData ? MessageImportance.Normal : default,
eventTimestamp: withOptionalData ? DateTime.Parse("3/1/2017 11:11:56 AM") : DateTime.Now,
messageArgs: withOptionalData ? new object[] { "arg0val", "arg1val" } : null)
{
ExtendedData = withOptionalData ? "{'long-json':'mostly-strings'}" : null,
ExtendedMetadata = withOptionalData ? new Dictionary<string, string?> { { "m1", "v1" }, { "m2", "v2" } } : null,
BuildEventContext = withOptionalData ? new BuildEventContext(1, 2, 3, 4, 5, 6, 7) : null,
};
using MemoryStream stream = new MemoryStream();
using BinaryWriter bw = new BinaryWriter(stream);
arg.WriteToStream(bw);
stream.Position = 0;
using BinaryReader br = new BinaryReader(stream);
ExtendedBuildMessageEventArgs argDeserialized = new();
argDeserialized.CreateFromStream(br, 80);
argDeserialized.Should().BeEquivalentTo(arg);
}
[Fact]
public void ExtendedCustomBuildEventArgs_Ctors()
{
var ea = new ExtendedCustomBuildEventArgs();
ea = new ExtendedCustomBuildEventArgs("type");
ea = new ExtendedCustomBuildEventArgs("type", "Message {0}", "Help", "sender");
ea = new ExtendedCustomBuildEventArgs("type", "Message {0}", "Help", "sender", DateTime.Now);
ea = new ExtendedCustomBuildEventArgs("type", "Message {0}", "Help", "sender", DateTime.Now, "arg1");
ea = new ExtendedCustomBuildEventArgs("type");
ea = new ExtendedCustomBuildEventArgs("type", null, null, null);
ea = new ExtendedCustomBuildEventArgs("type", null, null, null, default(DateTime));
ea = new ExtendedCustomBuildEventArgs("type", null, null, null, default(DateTime), null);
}
[Fact]
public void ExtendedBuildErrorEventArgs_Ctors()
{
var ea = new ExtendedBuildErrorEventArgs();
ea = new ExtendedBuildErrorEventArgs("type", "Subcategory", "Code", "File", 1, 2, 3, 4, "Message", "HelpKeyword", "sender");
ea = new ExtendedBuildErrorEventArgs("type", "Subcategory", "Code", "File", 1, 2, 3, 4, "Message", "HelpKeyword", "sender", DateTime.Now);
ea = new ExtendedBuildErrorEventArgs("type", "Subcategory", "Code", "File", 1, 2, 3, 4, "{0}", "HelpKeyword", "sender", DateTime.Now, "Message");
ea = new ExtendedBuildErrorEventArgs("type", "Subcategory", "Code", "File", 1, 2, 3, 4, "{0}", "HelpKeyword", "sender", "HelpLink", DateTime.Now, "Message");
ea = new ExtendedBuildErrorEventArgs("type", null, null, null, 1, 2, 3, 4, null, null, null);
ea = new ExtendedBuildErrorEventArgs("type", null, null, null, 1, 2, 3, 4, null, null, null, DateTime.Now);
ea = new ExtendedBuildErrorEventArgs("type", null, null, null, 1, 2, 3, 4, null, null, null, null, DateTime.Now, null);
}
[Fact]
public void ExtendedBuildWarningEventArgs_Ctors()
{
var ea = new ExtendedBuildWarningEventArgs();
ea = new ExtendedBuildWarningEventArgs("type", "Subcategory", "Code", "File", 1, 2, 3, 4, "Message", "HelpKeyword", "sender");
ea = new ExtendedBuildWarningEventArgs("type", "Subcategory", "Code", "File", 1, 2, 3, 4, "Message", "HelpKeyword", "sender", DateTime.Now);
ea = new ExtendedBuildWarningEventArgs("type", "Subcategory", "Code", "File", 1, 2, 3, 4, "{0}", "HelpKeyword", "sender", DateTime.Now, "Message");
ea = new ExtendedBuildWarningEventArgs("type", "Subcategory", "Code", "File", 1, 2, 3, 4, "{0}", "HelpKeyword", "sender", "HelpLink", DateTime.Now, "Message");
ea = new ExtendedBuildWarningEventArgs("type", null, null, null, 1, 2, 3, 4, null, null, null);
ea = new ExtendedBuildWarningEventArgs("type", null, null, null, 1, 2, 3, 4, null, null, null, DateTime.Now);
ea = new ExtendedBuildWarningEventArgs("type", null, null, null, 1, 2, 3, 4, null, null, null, null, DateTime.Now, null);
}
[Fact]
public void ExtendedBuildMessageEventArgs_Ctors()
{
var ea = new ExtendedBuildMessageEventArgs();
ea = new ExtendedBuildMessageEventArgs("type");
ea = new ExtendedBuildMessageEventArgs("type", "Message", "HelpKeyword", "sender", MessageImportance.High);
ea = new ExtendedBuildMessageEventArgs("type", "Message", "HelpKeyword", "sender", MessageImportance.High, DateTime.Now);
ea = new ExtendedBuildMessageEventArgs("type", "Message", "HelpKeyword", "sender", MessageImportance.High, DateTime.Now, "arg1");
ea = new ExtendedBuildMessageEventArgs("type", "Subcategory", "Code", "File", 1, 2, 3, 4, "Message", "HelpKeyword", "sender", MessageImportance.High);
ea = new ExtendedBuildMessageEventArgs("type", "Subcategory", "Code", "File", 1, 2, 3, 4, "Message", "HelpKeyword", "sender", MessageImportance.High, DateTime.Now);
ea = new ExtendedBuildMessageEventArgs("type", "Subcategory", "Code", "File", 1, 2, 3, 4, "{0}", "HelpKeyword", "sender", MessageImportance.High, DateTime.Now, "Message");
ea = new ExtendedBuildMessageEventArgs("type");
ea = new ExtendedBuildMessageEventArgs("type", null, null, null, default);
ea = new ExtendedBuildMessageEventArgs("type", null, null, null, default, DateTime.Now);
ea = new ExtendedBuildMessageEventArgs("type", null, null, null, default, default, null);
ea = new ExtendedBuildMessageEventArgs("type", null, null, null, 1, 2, 3, 4, null, null, null, default);
ea = new ExtendedBuildMessageEventArgs("type", null, null, null, 1, 2, 3, 4, null, null, null, default, DateTime.Now);
ea = new ExtendedBuildMessageEventArgs("type", null, null, null, 1, 2, 3, 4, null, null, null, default, DateTime.Now, null);
}
}

Просмотреть файл

@ -11,6 +11,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" />
<PackageReference Include="Microsoft.IO.Redist" Condition="'$(FeatureMSIORedist)' == 'true'" />
<PackageReference Include="Microsoft.VisualStudio.Setup.Configuration.Interop" Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'" />
<PackageReference Include="Shouldly" />

Просмотреть файл

@ -0,0 +1,126 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Shared;
namespace Microsoft.Build.Framework;
/// <summary>
/// Generic custom error events including extended data for event enriching.
/// Extended data are implemented by <see cref="IExtendedBuildEventArgs"/>
/// </summary>
public sealed class ExtendedBuildErrorEventArgs : BuildErrorEventArgs, IExtendedBuildEventArgs
{
/// <inheritdoc />
public string ExtendedType { get; set; }
/// <inheritdoc />
public Dictionary<string, string?>? ExtendedMetadata { get; set; }
/// <inheritdoc />
public string? ExtendedData { get; set; }
/// <summary>
/// Default constructor. Used for deserialization.
/// </summary>
internal ExtendedBuildErrorEventArgs() : this("undefined") { }
/// <summary>
/// This constructor specifies only type of extended data.
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
public ExtendedBuildErrorEventArgs(string type) => ExtendedType = type;
/// <summary>
/// This constructor allows all event data to be initialized
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="subcategory">event sub-category</param>
/// <param name="code">event code</param>
/// <param name="file">file associated with the event</param>
/// <param name="lineNumber">line number (0 if not applicable)</param>
/// <param name="columnNumber">column number (0 if not applicable)</param>
/// <param name="endLineNumber">end line number (0 if not applicable)</param>
/// <param name="endColumnNumber">end column number (0 if not applicable)</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of event sender</param>
public ExtendedBuildErrorEventArgs(string type, string? subcategory, string? code, string? file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber,
string? message, string? helpKeyword, string? senderName)
: base(subcategory, code, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, helpKeyword, senderName) => ExtendedType = type;
/// <summary>
/// This constructor which allows a timestamp to be set
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="subcategory">event sub-category</param>
/// <param name="code">event code</param>
/// <param name="file">file associated with the event</param>
/// <param name="lineNumber">line number (0 if not applicable)</param>
/// <param name="columnNumber">column number (0 if not applicable)</param>
/// <param name="endLineNumber">end line number (0 if not applicable)</param>
/// <param name="endColumnNumber">end column number (0 if not applicable)</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of event sender</param>
/// <param name="eventTimestamp">Timestamp when event was created</param>
public ExtendedBuildErrorEventArgs(string type, string? subcategory, string? code, string? file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber,
string? message, string? helpKeyword, string? senderName, DateTime eventTimestamp)
: base(subcategory, code, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, helpKeyword, senderName, eventTimestamp) => ExtendedType = type;
/// <summary>
/// This constructor which allows a timestamp to be set
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="subcategory">event sub-category</param>
/// <param name="code">event code</param>
/// <param name="file">file associated with the event</param>
/// <param name="lineNumber">line number (0 if not applicable)</param>
/// <param name="columnNumber">column number (0 if not applicable)</param>
/// <param name="endLineNumber">end line number (0 if not applicable)</param>
/// <param name="endColumnNumber">end column number (0 if not applicable)</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of event sender</param>
/// <param name="eventTimestamp">Timestamp when event was created</param>
/// <param name="messageArgs">message arguments</param>
public ExtendedBuildErrorEventArgs(string type, string? subcategory, string? code, string? file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber,
string? message, string? helpKeyword, string? senderName, DateTime eventTimestamp, params object[]? messageArgs)
: base(subcategory, code, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, helpKeyword, senderName, eventTimestamp, messageArgs) => ExtendedType = type;
/// <summary>
/// This constructor which allows a timestamp to be set
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="subcategory">event sub-category</param>
/// <param name="code">event code</param>
/// <param name="file">file associated with the event</param>
/// <param name="lineNumber">line number (0 if not applicable)</param>
/// <param name="columnNumber">column number (0 if not applicable)</param>
/// <param name="endLineNumber">end line number (0 if not applicable)</param>
/// <param name="endColumnNumber">end column number (0 if not applicable)</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="helpLink">A link pointing to more information about the error </param>
/// <param name="senderName">name of event sender</param>
/// <param name="eventTimestamp">Timestamp when event was created</param>
/// <param name="messageArgs">message arguments</param>
public ExtendedBuildErrorEventArgs(string type, string? subcategory, string? code, string? file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber,
string? message, string? helpKeyword, string? senderName, string? helpLink, DateTime eventTimestamp, params object[]? messageArgs)
: base(subcategory, code, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, helpKeyword, senderName, helpLink, eventTimestamp, messageArgs) => ExtendedType = type;
internal override void WriteToStream(BinaryWriter writer)
{
base.WriteToStream(writer);
writer.WriteExtendedBuildEventData(this);
}
internal override void CreateFromStream(BinaryReader reader, int version)
{
base.CreateFromStream(reader, version);
reader.ReadExtendedBuildEventData(this);
}
}

Просмотреть файл

@ -0,0 +1,144 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Shared;
namespace Microsoft.Build.Framework;
/// <summary>
/// Generic custom build events including extended data for event enriching.
/// Extended data are implemented by <see cref="IExtendedBuildEventArgs"/>
/// </summary>
public sealed class ExtendedBuildMessageEventArgs : BuildMessageEventArgs, IExtendedBuildEventArgs
{
/// <inheritdoc />
public string ExtendedType { get; set; }
/// <inheritdoc />
public Dictionary<string, string?>? ExtendedMetadata { get; set; }
/// <inheritdoc />
public string? ExtendedData { get; set; }
/// <summary>
/// Default constructor. Used for deserialization.
/// </summary>
internal ExtendedBuildMessageEventArgs() : this("undefined") { }
/// <summary>
/// This constructor specifies only type of extended data.
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
public ExtendedBuildMessageEventArgs(string type) => ExtendedType = type;
/// <summary>
/// This constructor allows all event data to be initialized
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of event sender</param>
/// <param name="importance">importance of the message</param>
public ExtendedBuildMessageEventArgs(string type, string? message, string? helpKeyword, string? senderName, MessageImportance importance)
: base(message, helpKeyword, senderName, importance) => ExtendedType = type;
/// <summary>
/// This constructor allows a timestamp to be set
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of event sender</param>
/// <param name="importance">importance of the message</param>
/// <param name="eventTimestamp">Timestamp when event was created</param>
public ExtendedBuildMessageEventArgs(string type, string? message, string? helpKeyword, string? senderName, MessageImportance importance, DateTime eventTimestamp)
: base(message, helpKeyword, senderName, importance, eventTimestamp) => ExtendedType = type;
/// <summary>
/// This constructor allows a timestamp to be set
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of event sender</param>
/// <param name="importance">importance of the message</param>
/// <param name="eventTimestamp">Timestamp when event was created</param>
/// <param name="messageArgs">message arguments</param>
public ExtendedBuildMessageEventArgs(string type, string? message, string? helpKeyword, string? senderName, MessageImportance importance, DateTime eventTimestamp, params object[]? messageArgs)
: base(message, helpKeyword, senderName, importance, eventTimestamp, messageArgs) => ExtendedType = type;
/// <summary>
/// This constructor allows all event data to be initialized
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="subcategory">event sub-category</param>
/// <param name="code">event code</param>
/// <param name="file">file associated with the event</param>
/// <param name="lineNumber">line number (0 if not applicable)</param>
/// <param name="columnNumber">column number (0 if not applicable)</param>
/// <param name="endLineNumber">end line number (0 if not applicable)</param>
/// <param name="endColumnNumber">end column number (0 if not applicable)</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of event sender</param>
/// <param name="importance">importance of the message</param>
public ExtendedBuildMessageEventArgs(string type, string? subcategory, string? code, string? file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber,
string? message, string? helpKeyword, string? senderName, MessageImportance importance)
: base(subcategory, code, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, helpKeyword, senderName, importance) => ExtendedType = type;
/// <summary>
/// This constructor which allows a timestamp to be set
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="subcategory">event sub-category</param>
/// <param name="code">event code</param>
/// <param name="file">file associated with the event</param>
/// <param name="lineNumber">line number (0 if not applicable)</param>
/// <param name="columnNumber">column number (0 if not applicable)</param>
/// <param name="endLineNumber">end line number (0 if not applicable)</param>
/// <param name="endColumnNumber">end column number (0 if not applicable)</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of event sender</param>
/// <param name="importance">importance of the message</param>
/// <param name="eventTimestamp">Timestamp when event was created</param>
public ExtendedBuildMessageEventArgs(string type, string? subcategory, string? code, string? file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber,
string? message, string? helpKeyword, string? senderName, MessageImportance importance, DateTime eventTimestamp)
: base(subcategory, code, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, helpKeyword, senderName, importance, eventTimestamp) => ExtendedType = type;
/// <summary>
/// This constructor which allows a timestamp to be set
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="subcategory">event sub-category</param>
/// <param name="code">event code</param>
/// <param name="file">file associated with the event</param>
/// <param name="lineNumber">line number (0 if not applicable)</param>
/// <param name="columnNumber">column number (0 if not applicable)</param>
/// <param name="endLineNumber">end line number (0 if not applicable)</param>
/// <param name="endColumnNumber">end column number (0 if not applicable)</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of event sender</param>
/// <param name="importance">importance of the message</param>
/// <param name="eventTimestamp">Timestamp when event was created</param>
/// <param name="messageArgs">message arguments</param>
public ExtendedBuildMessageEventArgs(string type, string? subcategory, string? code, string? file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber,
string? message, string? helpKeyword, string? senderName, MessageImportance importance, DateTime eventTimestamp, params object[]? messageArgs)
: base(subcategory, code, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, helpKeyword, senderName, importance, eventTimestamp, messageArgs) => ExtendedType = type;
internal override void WriteToStream(BinaryWriter writer)
{
base.WriteToStream(writer);
writer.WriteExtendedBuildEventData(this);
}
internal override void CreateFromStream(BinaryReader reader, int version)
{
base.CreateFromStream(reader, version);
reader.ReadExtendedBuildEventData(this);
}
}

Просмотреть файл

@ -0,0 +1,126 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Shared;
namespace Microsoft.Build.Framework;
/// <summary>
/// Generic custom warning events including extended data for event enriching.
/// Extended data are implemented by <see cref="IExtendedBuildEventArgs"/>
/// </summary>
public sealed class ExtendedBuildWarningEventArgs : BuildWarningEventArgs, IExtendedBuildEventArgs
{
/// <inheritdoc />
public string ExtendedType { get; set; }
/// <inheritdoc />
public Dictionary<string, string?>? ExtendedMetadata { get; set; }
/// <inheritdoc />
public string? ExtendedData { get; set; }
/// <summary>
/// Default constructor. Used for deserialization.
/// </summary>
internal ExtendedBuildWarningEventArgs() : this("undefined") { }
/// <summary>
/// This constructor specifies only type of extended data.
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
public ExtendedBuildWarningEventArgs(string type) => ExtendedType = type;
/// <summary>
/// This constructor allows all event data to be initialized
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="subcategory">event sub-category</param>
/// <param name="code">event code</param>
/// <param name="file">file associated with the event</param>
/// <param name="lineNumber">line number (0 if not applicable)</param>
/// <param name="columnNumber">column number (0 if not applicable)</param>
/// <param name="endLineNumber">end line number (0 if not applicable)</param>
/// <param name="endColumnNumber">end column number (0 if not applicable)</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of event sender</param>
public ExtendedBuildWarningEventArgs(string type, string? subcategory, string? code, string? file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber,
string? message, string? helpKeyword, string? senderName)
: base(subcategory, code, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, helpKeyword, senderName) => ExtendedType = type;
/// <summary>
/// This constructor which allows a timestamp to be set
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="subcategory">event sub-category</param>
/// <param name="code">event code</param>
/// <param name="file">file associated with the event</param>
/// <param name="lineNumber">line number (0 if not applicable)</param>
/// <param name="columnNumber">column number (0 if not applicable)</param>
/// <param name="endLineNumber">end line number (0 if not applicable)</param>
/// <param name="endColumnNumber">end column number (0 if not applicable)</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of event sender</param>
/// <param name="eventTimestamp">Timestamp when event was created</param>
public ExtendedBuildWarningEventArgs(string type, string? subcategory, string? code, string? file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber,
string? message, string? helpKeyword, string? senderName, DateTime eventTimestamp)
: base(subcategory, code, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, helpKeyword, senderName, eventTimestamp) => ExtendedType = type;
/// <summary>
/// This constructor which allows a timestamp to be set
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="subcategory">event sub-category</param>
/// <param name="code">event code</param>
/// <param name="file">file associated with the event</param>
/// <param name="lineNumber">line number (0 if not applicable)</param>
/// <param name="columnNumber">column number (0 if not applicable)</param>
/// <param name="endLineNumber">end line number (0 if not applicable)</param>
/// <param name="endColumnNumber">end column number (0 if not applicable)</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of event sender</param>
/// <param name="eventTimestamp">Timestamp when event was created</param>
/// <param name="messageArgs">message arguments</param>
public ExtendedBuildWarningEventArgs(string type, string? subcategory, string? code, string? file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber,
string? message, string? helpKeyword, string? senderName, DateTime eventTimestamp, params object[]? messageArgs)
: base(subcategory, code, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, helpKeyword, senderName, eventTimestamp, messageArgs) => ExtendedType = type;
/// <summary>
/// This constructor which allows a timestamp to be set
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="subcategory">event sub-category</param>
/// <param name="code">event code</param>
/// <param name="file">file associated with the event</param>
/// <param name="lineNumber">line number (0 if not applicable)</param>
/// <param name="columnNumber">column number (0 if not applicable)</param>
/// <param name="endLineNumber">end line number (0 if not applicable)</param>
/// <param name="endColumnNumber">end column number (0 if not applicable)</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="helpLink">A link pointing to more information about the error </param>
/// <param name="senderName">name of event sender</param>
/// <param name="eventTimestamp">Timestamp when event was created</param>
/// <param name="messageArgs">message arguments</param>
public ExtendedBuildWarningEventArgs(string type, string? subcategory, string? code, string? file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber,
string? message, string? helpKeyword, string? senderName, string? helpLink, DateTime eventTimestamp, params object[]? messageArgs)
: base(subcategory, code, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, helpKeyword, senderName, helpLink, eventTimestamp, messageArgs) => ExtendedType = type;
internal override void WriteToStream(BinaryWriter writer)
{
base.WriteToStream(writer);
writer.WriteExtendedBuildEventData(this);
}
internal override void CreateFromStream(BinaryReader reader, int version)
{
base.CreateFromStream(reader, version);
reader.ReadExtendedBuildEventData(this);
}
}

Просмотреть файл

@ -0,0 +1,80 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Shared;
namespace Microsoft.Build.Framework;
/// <summary>
/// Generic custom event.
/// Extended data are implemented by <see cref="IExtendedBuildEventArgs"/>
/// </summary>
public sealed class ExtendedCustomBuildEventArgs : CustomBuildEventArgs, IExtendedBuildEventArgs
{
/// <inheritdoc />
public string ExtendedType { get; set; }
/// <inheritdoc />
public Dictionary<string, string?>? ExtendedMetadata { get; set; }
/// <inheritdoc />
public string? ExtendedData { get; set; }
/// <summary>
/// This constructor allows event data to be initialized.
/// </summary>
/// <seealso cref="IExtendedBuildEventArgs.ExtendedType"/>
internal ExtendedCustomBuildEventArgs() : this("undefined") {}
/// <summary>
/// This constructor allows event data to be initialized.
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <seealso cref="IExtendedBuildEventArgs.ExtendedType"/>
public ExtendedCustomBuildEventArgs(string type) => ExtendedType = type;
/// <summary>
/// This constructor allows event data to be initialized.
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of sender</param>
public ExtendedCustomBuildEventArgs(string type, string? message, string? helpKeyword, string? senderName) : base(message, helpKeyword, senderName) => ExtendedType = type;
/// <summary>
/// This constructor allows event data to be initialized including timestamp.
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of sender</param>
/// <param name="eventTimestamp">Timestamp when event was created</param>
public ExtendedCustomBuildEventArgs(string type, string? message, string? helpKeyword, string? senderName, DateTime eventTimestamp) : base(message, helpKeyword, senderName, eventTimestamp) => ExtendedType = type;
/// <summary>
/// This constructor allows event data to be initialized including timestamp.
/// </summary>
/// <param name="type">Type of <see cref="IExtendedBuildEventArgs.ExtendedType"/>.</param>
/// <param name="message">text message</param>
/// <param name="helpKeyword">help keyword </param>
/// <param name="senderName">name of sender</param>
/// <param name="eventTimestamp">Timestamp when event was created</param>
/// <param name="messageArgs">Message arguments</param>
public ExtendedCustomBuildEventArgs(string type, string? message, string? helpKeyword, string? senderName, DateTime eventTimestamp, params object[]? messageArgs) : base(message, helpKeyword, senderName, eventTimestamp, messageArgs) => ExtendedType = type;
internal override void WriteToStream(BinaryWriter writer)
{
base.WriteToStream(writer);
writer.WriteExtendedBuildEventData(this);
}
internal override void CreateFromStream(BinaryReader reader, int version)
{
base.CreateFromStream(reader, version);
reader.ReadExtendedBuildEventData(this);
}
}

Просмотреть файл

@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.IO;
using Microsoft.Build.Shared;
#nullable disable
@ -16,6 +18,8 @@ namespace Microsoft.Build.Framework
// immutable; adding new fields in the next version of the type
// without following certain special FX guidelines, can break both
// forward and backward compatibility
// NOTE: Although this class has been modified and do not longer relay on [Serializable]
// and BinaryFormatter. We have left it [Serializable] for backward compatibility reasons.
[Serializable]
public class ExternalProjectFinishedEventArgs : CustomBuildEventArgs
{
@ -93,5 +97,19 @@ namespace Microsoft.Build.Framework
return succeeded;
}
}
internal override void WriteToStream(BinaryWriter writer)
{
base.WriteToStream(writer);
writer.WriteOptionalString(projectFile);
writer.Write(succeeded);
}
internal override void CreateFromStream(BinaryReader reader, int version)
{
base.CreateFromStream(reader, version);
projectFile = reader.ReadOptionalString();
succeeded = reader.ReadBoolean();
}
}
}

Просмотреть файл

@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.IO;
using Microsoft.Build.Shared;
#nullable disable
@ -16,6 +18,8 @@ namespace Microsoft.Build.Framework
// immutable; adding new fields in the next version of the type
// without following certain special FX guidelines, can break both
// forward and backward compatibility
// NOTE: Although this class has been modified and do not longer relay on [Serializable]
// and BinaryFormatter. We have left it [Serializable] for backward compatibility reasons.
[Serializable]
public class ExternalProjectStartedEventArgs : CustomBuildEventArgs
{
@ -95,5 +99,19 @@ namespace Microsoft.Build.Framework
return targetNames;
}
}
internal override void WriteToStream(BinaryWriter writer)
{
base.WriteToStream(writer);
writer.WriteOptionalString(projectFile);
writer.WriteOptionalString(targetNames);
}
internal override void CreateFromStream(BinaryReader reader, int version)
{
base.CreateFromStream(reader, version);
projectFile = reader.ReadOptionalString();
targetNames = reader.ReadOptionalString();
}
}
}

Просмотреть файл

@ -0,0 +1,33 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
namespace Microsoft.Build.Framework;
/// <summary>
/// Interface for Extended EventArgs to allow enriching particular events with extended data.
/// Deriving from EventArgs will be deprecated soon and using Extended EventArgs is recommended for custom Event Args.
/// </summary>
public interface IExtendedBuildEventArgs
{
/// <summary>
/// Unique string identifying type of extended data so receiver side knows how to interpret, deserialize and handle <see cref="ExtendedData"/>.
/// </summary>
string ExtendedType { get; set; }
/// <summary>
/// Metadata of <see cref="ExtendedData"/>.
/// Example usage:
/// - data which needed in custom code to properly routing this message without interpreting/deserializing <see cref="ExtendedData"/>.
/// - simple extended data can be transferred in form of dictionary key-value per one extended property.
/// </summary>
Dictionary<string, string?>? ExtendedMetadata { get; set; }
/// <summary>
/// Transparent data as string.
/// Custom code is responsible to serialize and deserialize this string to structured data - if needed.
/// Custom code can use any serialization they deem safe - e.g. json for textual data, base64 for binary data...
/// </summary>
string? ExtendedData { get; set; }
}

Просмотреть файл

@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using Microsoft.Build.Shared;
using System.IO;
#nullable disable
@ -27,5 +29,19 @@ namespace Microsoft.Build.Framework
this.metaprojectXml = metaprojectXml;
this.ProjectFile = metaprojectPath;
}
internal override void WriteToStream(BinaryWriter writer)
{
base.WriteToStream(writer);
writer.WriteOptionalString(metaprojectXml);
}
internal override void CreateFromStream(BinaryReader reader, int version)
{
base.CreateFromStream(reader, version);
metaprojectXml = reader.ReadOptionalString();
}
}
}

Просмотреть файл

@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.IO;
using Microsoft.Build.Shared;
#nullable disable
@ -56,5 +58,23 @@ namespace Microsoft.Build.Framework
/// The source of the property.
/// </summary>
public string PropertySource { get; set; }
internal override void WriteToStream(BinaryWriter writer)
{
base.WriteToStream(writer);
writer.WriteOptionalString(PropertyName);
writer.WriteOptionalString(PropertyValue);
writer.WriteOptionalString(PropertySource);
}
internal override void CreateFromStream(BinaryReader reader, int version)
{
base.CreateFromStream(reader, version);
PropertyName = reader.ReadOptionalString();
PropertyValue = reader.ReadOptionalString();
PropertySource = reader.ReadOptionalString();
}
}
}

Просмотреть файл

@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.IO;
using Microsoft.Build.Shared;
#nullable disable
@ -79,5 +81,25 @@ namespace Microsoft.Build.Framework
return RawMessage;
}
}
internal override void WriteToStream(BinaryWriter writer)
{
base.WriteToStream(writer);
writer.WriteOptionalString(PropertyName);
writer.WriteOptionalString(NewValue);
writer.WriteOptionalString(PreviousValue);
writer.WriteOptionalString(Location);
}
internal override void CreateFromStream(BinaryReader reader, int version)
{
base.CreateFromStream(reader, version);
PropertyName = reader.ReadOptionalString();
NewValue = reader.ReadOptionalString();
PreviousValue = reader.ReadOptionalString();
Location = reader.ReadOptionalString();
}
}
}

Просмотреть файл

@ -372,6 +372,29 @@ namespace Microsoft.Build.Framework
}
}
/// <summary>
/// Allows displaying the deprecation warning for BinaryFormatter in your current environment.
/// </summary>
public bool EnableWarningOnCustomBuildEvent
{
get
{
var value = Environment.GetEnvironmentVariable("MSBUILDCUSTOMBUILDEVENTWARNING");
if (value == null)
{
// If variable is not set explicitly, for .NETCORE warning appears.
#if RUNTIME_TYPE_NETCORE
return true;
#else
return false;
#endif
}
return value == "1";
}
}
private static bool? ParseNullableBoolFromEnvironmentVariable(string environmentVariable)
{
var value = Environment.GetEnvironmentVariable(environmentVariable);

Просмотреть файл

@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.IO;
using Microsoft.Build.Shared;
#nullable disable
@ -42,5 +44,18 @@ namespace Microsoft.Build.Framework
/// The name of the uninitialized property that was read.
/// </summary>
public string PropertyName { get; set; }
internal override void WriteToStream(BinaryWriter writer)
{
base.WriteToStream(writer);
writer.WriteOptionalString(PropertyName);
}
internal override void CreateFromStream(BinaryReader reader, int version)
{
base.CreateFromStream(reader, version);
PropertyName = reader.ReadOptionalString();
}
}
}

Просмотреть файл

@ -1147,7 +1147,9 @@ namespace Microsoft.Build.CommandLine
if (_nodeEndpoint?.LinkStatus == LinkStatus.Active)
{
#pragma warning disable SYSLIB0050
if (!e.GetType().GetTypeInfo().IsSerializable)
// Types which are not serializable and are not IExtendedBuildEventArgs as
// those always implement custom serialization by WriteToStream and CreateFromStream.
if (!e.GetType().GetTypeInfo().IsSerializable && e is not IExtendedBuildEventArgs)
#pragma warning disable SYSLIB0050
{
// log a warning and bail. This will end up re-calling SendBuildEvent, but we know for a fact
@ -1156,7 +1158,8 @@ namespace Microsoft.Build.CommandLine
return;
}
_nodeEndpoint.SendData(new LogMessagePacket(new KeyValuePair<int, BuildEventArgs>(_currentConfiguration.NodeId, e)));
LogMessagePacket logMessage = new LogMessagePacket(new KeyValuePair<int, BuildEventArgs>(_currentConfiguration.NodeId, e));
_nodeEndpoint.SendData(logMessage);
}
}

Просмотреть файл

@ -61,6 +61,9 @@
<Compile Include="..\Framework\ITaskItem2.cs">
<Link>ITaskItem2.cs</Link>
</Compile>
<Compile Include="..\Framework\IExtendedBuildEventArgs.cs">
<Link>IExtendedBuildEventArgs.cs</Link>
</Compile>
<Compile Include="..\Framework\AssemblyUtilities.cs" />
<Compile Include="..\Framework\ResponseFileUsedEventArgs.cs" />
<Compile Include="..\Shared\BufferedReadStream.cs" />

Просмотреть файл

@ -99,5 +99,30 @@ namespace Microsoft.Build.Shared
{
return new Guid(reader.ReadBytes(sizeof(Guid)));
}
public static void ReadExtendedBuildEventData(this BinaryReader reader, IExtendedBuildEventArgs data)
{
data.ExtendedType = reader.ReadString();
data.ExtendedData = reader.ReadOptionalString();
bool haveMetadata = reader.ReadBoolean();
if (haveMetadata)
{
data.ExtendedMetadata = new();
int count = reader.Read7BitEncodedInt();
for (int i = 0; i < count; i++)
{
string key = reader.ReadString();
string? value = reader.ReadOptionalString();
data.ExtendedMetadata.Add(key, value);
}
}
else
{
data.ExtendedMetadata = null;
}
}
}
}

Просмотреть файл

@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using Microsoft.Build.Framework;
@ -111,5 +112,22 @@ namespace Microsoft.Build.Shared
}
}
}
public static void WriteExtendedBuildEventData(this BinaryWriter writer, IExtendedBuildEventArgs data)
{
writer.Write(data.ExtendedType);
writer.WriteOptionalString(data.ExtendedData);
writer.Write(data.ExtendedMetadata != null);
if (data.ExtendedMetadata != null)
{
writer.Write7BitEncodedInt(data.ExtendedMetadata.Count);
foreach (KeyValuePair<string, string?> kvp in data.ExtendedMetadata)
{
writer.Write(kvp.Key);
writer.WriteOptionalString(kvp.Value);
}
}
}
}
}

Просмотреть файл

@ -145,6 +145,61 @@ namespace Microsoft.Build.Shared
/// Event is an AssemblyLoadBuildEventArgs
/// </summary>
AssemblyLoadEvent = 21,
/// <summary>
/// Event is <see cref="ExternalProjectStartedEventArgs"/>
/// </summary>
ExternalProjectStartedEvent = 22,
/// <summary>
/// Event is <see cref="ExternalProjectFinishedEventArgs"/>
/// </summary>
ExternalProjectFinishedEvent = 23,
/// <summary>
/// Event is <see cref="ExtendedCustomBuildEventArgs"/>
/// </summary>
ExtendedCustomEvent = 24,
/// <summary>
/// Event is <see cref="ExtendedBuildErrorEventArgs"/>
/// </summary>
ExtendedBuildErrorEvent = 25,
/// <summary>
/// Event is <see cref="ExtendedBuildWarningEventArgs"/>
/// </summary>
ExtendedBuildWarningEvent = 26,
/// <summary>
/// Event is <see cref="ExtendedBuildMessageEventArgs"/>
/// </summary>
ExtendedBuildMessageEvent = 27,
/// <summary>
/// Event is <see cref="CriticalBuildMessageEventArgs"/>
/// </summary>
CriticalBuildMessage = 28,
/// <summary>
/// Event is <see cref="MetaprojectGeneratedEventArgs"/>
/// </summary>
MetaprojectGenerated = 29,
/// <summary>
/// Event is <see cref="PropertyInitialValueSetEventArgs"/>
/// </summary>
PropertyInitialValueSet = 30,
/// <summary>
/// Event is <see cref="PropertyReassignmentEventArgs"/>
/// </summary>
PropertyReassignment = 31,
/// <summary>
/// Event is <see cref="UninitializedPropertyReadEventArgs"/>
/// </summary>
UninitializedPropertyRead = 32
}
#endregion
@ -230,8 +285,9 @@ namespace Microsoft.Build.Shared
/// <summary>
/// Constructor for deserialization
/// </summary>
protected LogMessagePacketBase(ITranslator translator)
protected LogMessagePacketBase(ITranslator translator, TargetFinishedTranslator targetFinishedTranslator = null)
{
_targetFinishedTranslator = targetFinishedTranslator;
Translate(translator);
}
@ -339,7 +395,8 @@ namespace Microsoft.Build.Shared
#if !TASKHOST && !MSBUILDENTRYPOINTEXE
if (_buildEvent is ProjectEvaluationStartedEventArgs
or ProjectEvaluationFinishedEventArgs
or EnvironmentVariableReadEventArgs)
or EnvironmentVariableReadEventArgs
or ResponseFileUsedEventArgs)
{
// switch to serialization methods that we provide in this file
// and don't use the WriteToStream inherited from LazyFormattedBuildEventArgs
@ -536,6 +593,17 @@ namespace Microsoft.Build.Shared
LoggingEventType.ProjectImportedEvent => new ProjectImportedEventArgs(),
LoggingEventType.TargetSkipped => new TargetSkippedEventArgs(),
LoggingEventType.Telemetry => new TelemetryEventArgs(),
LoggingEventType.ExtendedCustomEvent => new ExtendedCustomBuildEventArgs(),
LoggingEventType.ExtendedBuildErrorEvent => new ExtendedBuildErrorEventArgs(),
LoggingEventType.ExtendedBuildWarningEvent => new ExtendedBuildWarningEventArgs(),
LoggingEventType.ExtendedBuildMessageEvent => new ExtendedBuildMessageEventArgs(),
LoggingEventType.ExternalProjectStartedEvent => new ExternalProjectStartedEventArgs(null, null, null, null, null),
LoggingEventType.ExternalProjectFinishedEvent => new ExternalProjectFinishedEventArgs(null, null, null, null, false),
LoggingEventType.CriticalBuildMessage => new CriticalBuildMessageEventArgs(null, null, null, -1, -1, -1, -1, null, null, null),
LoggingEventType.MetaprojectGenerated => new MetaprojectGeneratedEventArgs(null, null, null),
LoggingEventType.PropertyInitialValueSet => new PropertyInitialValueSetEventArgs(),
LoggingEventType.PropertyReassignment => new PropertyReassignmentEventArgs(),
LoggingEventType.UninitializedPropertyRead => new UninitializedPropertyReadEventArgs(),
#endif
_ => throw new InternalErrorException("Should not get to the default of GetBuildEventArgFromId ID: " + _eventType)
};
@ -573,6 +641,15 @@ namespace Microsoft.Build.Shared
{
return LoggingEventType.ProjectStartedEvent;
}
else if (eventType == typeof(ExternalProjectStartedEventArgs))
{
return LoggingEventType.ExternalProjectStartedEvent;
}
else if (eventType == typeof(ExternalProjectFinishedEventArgs))
{
return LoggingEventType.ExternalProjectFinishedEvent;
}
#if !TASKHOST
else if (eventType == typeof(ProjectEvaluationFinishedEventArgs))
{
@ -598,6 +675,42 @@ namespace Microsoft.Build.Shared
{
return LoggingEventType.AssemblyLoadEvent;
}
else if (eventType == typeof(ExtendedCustomBuildEventArgs))
{
return LoggingEventType.ExtendedCustomEvent;
}
else if (eventType == typeof(ExtendedBuildErrorEventArgs))
{
return LoggingEventType.ExtendedBuildErrorEvent;
}
else if (eventType == typeof(ExtendedBuildWarningEventArgs))
{
return LoggingEventType.ExtendedBuildWarningEvent;
}
else if (eventType == typeof(ExtendedBuildMessageEventArgs))
{
return LoggingEventType.ExtendedBuildMessageEvent;
}
else if (eventType == typeof(CriticalBuildMessageEventArgs))
{
return LoggingEventType.CriticalBuildMessage;
}
else if (eventType == typeof(MetaprojectGeneratedEventArgs))
{
return LoggingEventType.MetaprojectGenerated;
}
else if (eventType == typeof(PropertyInitialValueSetEventArgs))
{
return LoggingEventType.PropertyInitialValueSet;
}
else if (eventType == typeof(PropertyReassignmentEventArgs))
{
return LoggingEventType.PropertyReassignment;
}
else if (eventType == typeof(UninitializedPropertyReadEventArgs))
{
return LoggingEventType.UninitializedPropertyRead;
}
#endif
else if (eventType == typeof(TargetStartedEventArgs))
{
@ -690,12 +803,6 @@ namespace Microsoft.Build.Shared
case LoggingEventType.BuildWarningEvent:
WriteBuildWarningEventToStream((BuildWarningEventArgs)buildEvent, translator);
break;
case LoggingEventType.ProjectStartedEvent:
WriteExternalProjectStartedEventToStream((ExternalProjectStartedEventArgs)buildEvent, translator);
break;
case LoggingEventType.ProjectFinishedEvent:
WriteExternalProjectFinishedEventToStream((ExternalProjectFinishedEventArgs)buildEvent, translator);
break;
case LoggingEventType.EnvironmentVariableReadEvent:
WriteEnvironmentVariableReadEventArgs((EnvironmentVariableReadEventArgs)buildEvent, translator);
break;
@ -712,37 +819,20 @@ namespace Microsoft.Build.Shared
private void WriteEnvironmentVariableReadEventArgs(EnvironmentVariableReadEventArgs environmentVariableReadEventArgs, ITranslator translator)
{
string name = environmentVariableReadEventArgs.EnvironmentVariableName;
MessageImportance importance = environmentVariableReadEventArgs.Importance;
translator.Translate(ref name);
BuildEventContext context = environmentVariableReadEventArgs.BuildEventContext;
translator.TranslateEnum(ref importance, (int)importance);
#if !CLR2COMPATIBILITY
DateTime timestamp = environmentVariableReadEventArgs.RawTimestamp;
BuildEventContext context = environmentVariableReadEventArgs.BuildEventContext;
translator.Translate(ref timestamp);
translator.Translate(ref context);
#endif
}
/// <summary>
/// Serialize ExternalProjectFinished Event Argument to the stream
/// </summary>
private void WriteExternalProjectFinishedEventToStream(ExternalProjectFinishedEventArgs externalProjectFinishedEventArgs, ITranslator translator)
{
string projectFile = externalProjectFinishedEventArgs.ProjectFile;
translator.Translate(ref projectFile);
bool succeeded = externalProjectFinishedEventArgs.Succeeded;
translator.Translate(ref succeeded);
}
/// <summary>
/// ExternalProjectStartedEvent
/// </summary>
private void WriteExternalProjectStartedEventToStream(ExternalProjectStartedEventArgs externalProjectStartedEventArgs, ITranslator translator)
{
string projectFile = externalProjectStartedEventArgs.ProjectFile;
translator.Translate(ref projectFile);
string targetNames = externalProjectStartedEventArgs.TargetNames;
translator.Translate(ref targetNames);
}
#region Writes to Stream
/// <summary>
@ -829,7 +919,13 @@ namespace Microsoft.Build.Shared
private void WriteResponseFileUsedEventToStream(ResponseFileUsedEventArgs responseFileUsedEventArgs, ITranslator translator)
{
string filePath = responseFileUsedEventArgs.ResponseFilePath;
translator.Translate(ref filePath);
#if !CLR2COMPATIBILITY
DateTime timestamp = responseFileUsedEventArgs.RawTimestamp;
translator.Translate(ref timestamp);
#endif
}
#if !TASKHOST && !MSBUILDENTRYPOINTEXE
@ -1066,8 +1162,6 @@ namespace Microsoft.Build.Shared
{
LoggingEventType.TaskCommandLineEvent => ReadTaskCommandLineEventFromStream(translator, message, helpKeyword, senderName),
LoggingEventType.BuildErrorEvent => ReadTaskBuildErrorEventFromStream(translator, message, helpKeyword, senderName),
LoggingEventType.ProjectStartedEvent => ReadExternalProjectStartedEventFromStream(translator, message, helpKeyword, senderName),
LoggingEventType.ProjectFinishedEvent => ReadExternalProjectFinishedEventFromStream(translator, message, helpKeyword, senderName),
LoggingEventType.BuildMessageEvent => ReadBuildMessageEventFromStream(translator, message, helpKeyword, senderName),
LoggingEventType.ResponseFileUsedEvent => ReadResponseFileUsedEventFromStream(translator, message, helpKeyword, senderName),
LoggingEventType.BuildWarningEvent => ReadBuildWarningEventFromStream(translator, message, helpKeyword, senderName),
@ -1082,60 +1176,24 @@ namespace Microsoft.Build.Shared
private EnvironmentVariableReadEventArgs ReadEnvironmentVariableReadEventFromStream(ITranslator translator, string message, string helpKeyword, string senderName)
{
string environmentVariableName = null;
MessageImportance importance = default;
translator.Translate(ref environmentVariableName);
BuildEventContext context = null;
translator.TranslateEnum(ref importance, (int)importance);
EnvironmentVariableReadEventArgs args = new(environmentVariableName, message, helpKeyword, senderName, importance);
#if !CLR2COMPATIBILITY
DateTime timestamp = default;
BuildEventContext context = null;
translator.Translate(ref timestamp);
translator.Translate(ref context);
#endif
EnvironmentVariableReadEventArgs args = new(environmentVariableName, message);
args.RawTimestamp = timestamp;
args.BuildEventContext = context;
#endif
return args;
}
/// <summary>
/// Read and reconstruct a ProjectFinishedEventArgs from the stream
/// </summary>
private ExternalProjectFinishedEventArgs ReadExternalProjectFinishedEventFromStream(ITranslator translator, string message, string helpKeyword, string senderName)
{
string projectFile = null;
translator.Translate(ref projectFile);
bool succeeded = true;
translator.Translate(ref succeeded);
ExternalProjectFinishedEventArgs buildEvent =
new ExternalProjectFinishedEventArgs(
message,
helpKeyword,
senderName,
projectFile,
succeeded);
return buildEvent;
}
/// <summary>
/// Read and reconstruct a ProjectStartedEventArgs from the stream
/// </summary>
private ExternalProjectStartedEventArgs ReadExternalProjectStartedEventFromStream(ITranslator translator, string message, string helpKeyword, string senderName)
{
string projectFile = null;
translator.Translate(ref projectFile);
string targetNames = null;
translator.Translate(ref targetNames);
ExternalProjectStartedEventArgs buildEvent =
new ExternalProjectStartedEventArgs(
message,
helpKeyword,
senderName,
projectFile,
targetNames);
return buildEvent;
}
/// <summary>
/// Read and reconstruct a BuildWarningEventArgs from the stream
/// </summary>
@ -1256,6 +1314,14 @@ namespace Microsoft.Build.Shared
string responseFilePath = String.Empty;
translator.Translate(ref responseFilePath);
ResponseFileUsedEventArgs buildEvent = new ResponseFileUsedEventArgs(responseFilePath);
#if !CLR2COMPATIBILITY
DateTime timestamp = default;
translator.Translate(ref timestamp);
buildEvent.RawTimestamp = timestamp;
#endif
return buildEvent;
}

Просмотреть файл

@ -66,6 +66,9 @@
<data name="ExpectedEventToBeSerializable" Visibility="Public">
<value>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</value>
</data>
<data name="DeprecatedEventSerialization" Visibility="Public">
<value>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</value>
</data>
<data name="FileLocation" Visibility="Public">
<value>{0} ({1},{2})</value>
<comment>A file location to be embedded in a string.</comment>

5
src/Shared/Resources/xlf/Strings.shared.cs.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: Bylo nalezeno konfliktní sestavení pro sestavení úlohy {0} v umístění {1}.</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">Očekávalo se, že typ události {0} bude možné serializovat pomocí serializátoru .NET. Událost nebylo možné serializovat a byla ignorována.</target>

5
src/Shared/Resources/xlf/Strings.shared.de.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: Eine mit der Aufgabenassembly "{0}" in Konflikt stehende Assembly wurde in "{1}" gefunden.</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">Es wurde erwartet, dass der Ereignistyp "{0}" mithilfe des .NET-Serialisierers serialisierbar ist. Das Ereignis war nicht serialisierbar und wurde ignoriert.</target>

5
src/Shared/Resources/xlf/Strings.shared.es.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: Se detectó un ensamblado conflictivo para el ensamblado de tarea "{0}" en "{1}".</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">Se esperaba que el tipo de evento "{0}" fuera serializable con el serializador .NET. El evento no era serializable y se ha omitido.</target>

5
src/Shared/Resources/xlf/Strings.shared.fr.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: un assembly en conflit avec l'assembly de tâche "{0}" a été trouvé sur "{1}".</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">Le type d'événement "{0}" devait être sérialisable à l'aide du sérialiseur .NET. L'événement n'était pas sérialisable et a été ignoré.</target>

5
src/Shared/Resources/xlf/Strings.shared.it.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: rilevato un assembly in conflitto per l'assembly dell'attività "{0}" in "{1}".</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">È previsto un tipo di evento "{0}" serializzabile con il serializzatore .NET. L'evento non era serializzabile ed è stato ignorato.</target>

5
src/Shared/Resources/xlf/Strings.shared.ja.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: タスク アセンブリ "{0}" に対して競合しているアセンブリが "{1}" で見つかりました。</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">イベントの種類 "{0}" は .NET シリアライザーを使用してシリアル化可能であることが想定されていましたが、シリアル化可能でなかったため無視されました。</target>

5
src/Shared/Resources/xlf/Strings.shared.ko.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: 작업 어셈블리 "{0}"과(와) 충돌하는 어셈블리가 "{1}"에 있습니다.</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">이벤트 유형 "{0}"은(는) .NET serializer를 사용하여 serialize할 수 있어야 합니다. 이 이벤트는 serialize할 수 없으므로 무시되었습니다.</target>

5
src/Shared/Resources/xlf/Strings.shared.pl.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: Zestaw, który wywołuje konflikt z zestawem zadania „{0}”, został znaleziony w „{1}”.</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">Oczekiwano, że zdarzenie typu „{0}” będzie uszeregowane przy użyciu serializatora platformy .NET. Zdarzenie nie może podlegać szeregowaniu, dlatego zostało zignorowane.</target>

5
src/Shared/Resources/xlf/Strings.shared.pt-BR.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: Foi encontrado um assembly conflitante no assembly da tarefa "{0}" em "{1}".</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">Era esperado que o tipo de evento "{0}" fosse serializável usando o serializador .NET. O evento não era serializável e foi ignorado.</target>

5
src/Shared/Resources/xlf/Strings.shared.ru.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: в "{1}" обнаружена сборка, конфликтующая со сборкой задачи "{0}".</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">Необходимо, чтобы тип события "{0}" был сериализуемым с помощью сериализатора .NET. Событие не было сериализуемым и было пропущено.</target>

5
src/Shared/Resources/xlf/Strings.shared.tr.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: "{0}" görev derlemesi için "{1}" konumunda çakışan derleme bulundu.</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">"{0}" olay türünün .NET serileştiricisi kullanılarak serileştirilebilir olması bekleniyordu. Olay serileştirilebilir değildi ve yoksayıldı.</target>

5
src/Shared/Resources/xlf/Strings.shared.zh-Hans.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: 在“{1}”处发现了与任务程序集“{0}”冲突的程序集。</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">事件类型“{0}”应可以使用 .NET 序列化程序进行序列化。此事件不可序列化,已忽略它。</target>

5
src/Shared/Resources/xlf/Strings.shared.zh-Hant.xlf сгенерированный
Просмотреть файл

@ -22,6 +22,11 @@
<target state="translated">MSB4008: 已在 "{1}" 中發現工作組件 "{0}" 的衝突組件。</target>
<note>{StrBegin="MSB4008: "}UE: This message is shown when the type/class of a task cannot be resolved uniquely from a single assembly.</note>
</trans-unit>
<trans-unit id="DeprecatedEventSerialization">
<source>Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</source>
<target state="new">Usage of unsecure BinaryFormatter during serialization of custom event type '{0}'. This will be deprecated soon. Please use Extended*EventArgs instead. More info: https://aka.ms/msbuild/eventargs</target>
<note />
</trans-unit>
<trans-unit id="ExpectedEventToBeSerializable">
<source>Event type "{0}" was expected to be serializable using the .NET serializer. The event was not serializable and has been ignored.</source>
<target state="translated">事件類型 "{0}" 應該可以使用 .NET 序列化程式序列化。此事件不可序列化,已略過。</target>