diff --git a/src/MSBuildProjectCreator.UnitTests/BuildOutputTests.cs b/src/MSBuildProjectCreator.UnitTests/BuildOutputTests.cs
index 445c346..a001d60 100644
--- a/src/MSBuildProjectCreator.UnitTests/BuildOutputTests.cs
+++ b/src/MSBuildProjectCreator.UnitTests/BuildOutputTests.cs
@@ -21,7 +21,7 @@ public void ConsoleLog()
eventSource.OnErrorRaised("FDC8FB4F8E084055974580DF7CD7531E", "6496288436BE4E7CAE014F163914063C", "7B07B020E38343A89B3FA844A40895E4", 1, 2, 0, 0);
eventSource.OnWarningRaised("E00BBDAEEFAB45949AFEE1BF792B1691", "56206897E63F44159603D22BB7C08145", "C455F26F4D4543E78F109BCB00F02BE2", 1, 2, 0, 0);
eventSource.OnMessageRaised("55B991507D52403295E92E4FFA8704F3", MessageImportance.High);
- eventSource.OnMessageRaised("FA7FCCBE43B741998BAB399E74F2997D", MessageImportance.Normal);
+ eventSource.OnMessageRaised("FA7FCCBE43B741998BAB399E74F2997D");
eventSource.OnMessageRaised("67C0E0E52F2A45A981F3143BAF00A4A3", MessageImportance.Low);
});
diff --git a/src/MSBuildProjectCreator.UnitTests/ChooseTests.cs b/src/MSBuildProjectCreator.UnitTests/ChooseTests.cs
new file mode 100644
index 0000000..b0ff538
--- /dev/null
+++ b/src/MSBuildProjectCreator.UnitTests/ChooseTests.cs
@@ -0,0 +1,283 @@
+// Copyright (c) Jeff Kluge. All rights reserved.
+//
+// Licensed under the MIT license.
+
+using Microsoft.Build.Evaluation;
+using Shouldly;
+using Xunit;
+
+namespace Microsoft.Build.Utilities.ProjectCreation.UnitTests
+{
+ public class ChooseTests : MSBuildTestBase
+ {
+ [Fact]
+ public void ChooseComplex()
+ {
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .Choose()
+ .When("86578122B49842F891B9E4364611C4B5")
+ .WhenProperty("B7AF35A6A56D42EFACF4DFE1D7B0BC22", "0CA39A3C5E5348C4B5F1F50A33D8E6D8")
+ .WhenItemInclude("B5A8719D78D94961AFFA5134869C0DA5", "451053866BBB40B4A384EF5621994A65")
+ .WhenPropertyGroup("F192F2869950424BBE8FF979B12D98F8")
+ .WhenProperty("EB4919AA53C5457BB43F2E655469CF87", "1169C171C8F545D98691AB1DA5022763")
+ .When("ED64B6236EB94B639CF64DA27F4DAA21")
+ .WhenProperty("EA807B50DDD64BFAB67D74F34B2D091F", "8DB5478CDBC74BD1A222FE8FFA3F02A7")
+ .WhenItemInclude("F5624A5EE6B54AF6BBF6A03A163290A6", "4B45B6646D704CD8B06ED8401853C6F2")
+ .Otherwise()
+ .OtherwisePropertyGroup()
+ .OtherwiseProperty("EEE980CF390149DFB7B54B944B1F81C3", "7A886840832A4AACB0190A13E97D3502")
+ .OtherwiseItemGroup("84B3B0E939CE4F0CAABE555F3DD5940F")
+ .OtherwiseItemInclude("BDD653F0C8504129845B4CBBAD0732B1", "0887CC7FB1B842BD9B69AACD0ACBC6D3")
+ .OtherwiseItemGroup()
+ .OtherwiseItemInclude("C93C964CC1D6475BA622D37155E27398", "C005C57892AD48F8994C1003D91F8A01")
+ .Property("F5EA50D160D84FEA9D19049E41BD75EB", "2B50B6EF9CB148D583726948D7565E01")
+ .Choose()
+ .When("BFB1AB9E0D224C42AEB2A19A8247FD37")
+ .WhenProperty("DF4F395C964342C98430D7F9DD047D0F", "DCF0536D69BA4904BE25A69B1C834E92")
+ .WhenItemInclude("A9CA9BB3DFDE41808AA7646F44D628F3", "16405519E583482D8BAF5D7F23F13C2F")
+ .OtherwiseProperty("EF325D1CDDA249D396CEA0F6B6C52BFB", "8732DB2BD30E4334A9B0913DA6DA9E0F")
+ .OtherwiseItemInclude("A604962F0D14471C961BA98592A78ADC", "3224EC5ED0A743E2B4C32BC4E6AC4BAC")
+ .Xml
+ .ShouldBe(
+ @"
+
+
+
+ 0CA39A3C5E5348C4B5F1F50A33D8E6D8
+
+
+
+
+
+ 1169C171C8F545D98691AB1DA5022763
+
+
+
+
+ 8DB5478CDBC74BD1A222FE8FFA3F02A7
+
+
+
+
+
+
+
+ 7A886840832A4AACB0190A13E97D3502
+
+
+
+
+
+
+
+
+
+
+ 2B50B6EF9CB148D583726948D7565E01
+
+
+
+
+ DCF0536D69BA4904BE25A69B1C834E92
+
+
+
+
+
+
+
+ 8732DB2BD30E4334A9B0913DA6DA9E0F
+
+
+
+
+
+
+",
+ StringCompareShould.IgnoreLineEndings);
+ }
+
+ [Fact]
+ public void ChooseDuplicateOtherwiseThrows()
+ {
+ Assert.Throws(() =>
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .When("775FF5802F144DEDAACE58B9490C33BA")
+ .Otherwise()
+ .Otherwise())
+ .Message
+ .ShouldBe("You can only add one Otherwise to a Choose.");
+ }
+
+ [Fact]
+ public void ChooseSimple()
+ {
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .When("9E523BB0891C418C8F65DFF9AC8DAE4D")
+ .WhenProperty("A3E6CF45FEC246018B4EF3DBA9194874", "782A17D1FABD4109A7AF3FBF81C2BEE4")
+ .OtherwiseProperty("CED127BDCF6E4CD68320A7F74DFB753E", "636471FE65DE453489594A635A64C958")
+ .Xml
+ .ShouldBe(
+ @"
+
+
+
+ 782A17D1FABD4109A7AF3FBF81C2BEE4
+
+
+
+
+ 636471FE65DE453489594A635A64C958
+
+
+
+",
+ StringCompareShould.IgnoreLineEndings);
+ }
+
+ [Fact]
+ public void OtherwiseItemGroupIncludeSimple()
+ {
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .When("CD76E65E1E824325A4925A194AD4F483")
+ .OtherwiseItemInclude("CDC2199A17E246ABA6F265152F787089", "92FE0C66858E4D7DAA74D8E0EA2DB048")
+ .OtherwiseItemGroup("B7C857786BF3465AB66FBFFAC1685282")
+ .OtherwiseItemInclude("B8F32E43B164439E9BC571B44DAAC1C6", "C49C78223E25441FBC7564E29C7DDC4F")
+ .Xml
+ .ShouldBe(
+ @"
+
+
+
+
+
+
+
+
+
+
+
+",
+ StringCompareShould.IgnoreLineEndings);
+ }
+
+ [Fact]
+ public void OtherwiseItemGroupThowsIfNoWhen()
+ {
+ Assert.Throws(() =>
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .OtherwiseItemGroup())
+ .Message
+ .ShouldBe("You must add a When before adding an Otherwise.");
+ }
+
+ [Fact]
+ public void OtherwiseItemIncludeSimple()
+ {
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .When("FC8B0F3FC5AF46A0ACC25560933CF785")
+ .OtherwiseItemInclude("B799C10460D94BE5984EC263CFE3D137", "35E7FB0DAF0545A0B536C356D767FA16")
+ .OtherwiseItemInclude("C0BC9946435E4DDDB2EA6A2D2B646887", "9903791A0A484F628894BD9CDEFFCECC")
+ .Xml
+ .ShouldBe(
+ @"
+
+
+
+
+
+
+
+
+
+",
+ StringCompareShould.IgnoreLineEndings);
+ }
+
+ [Fact]
+ public void OtherwiseItemThowsIfNoWhen()
+ {
+ Assert.Throws(() =>
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .OtherwiseItemInclude("DF56AA18486E493E843BF397B1524E32", "6936461B06F8470EAB28C980E50F86E2"))
+ .Message
+ .ShouldBe("You must add a When before adding an Otherwise.");
+ }
+
+ [Fact]
+ public void OtherwisePropertyGroupThowsIfNoWhen()
+ {
+ Assert.Throws(() =>
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .OtherwisePropertyGroup())
+ .Message
+ .ShouldBe("You must add a When before adding an Otherwise.");
+ }
+
+ [Fact]
+ public void OtherwisePropertyThowsIfNoWhen()
+ {
+ Assert.Throws(() =>
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .OtherwiseProperty("C59717A7F40F40AE984A2B0DFDA165FC", "F070DA5E5F8A46619653DDE31818A23A"))
+ .Message
+ .ShouldBe("You must add a When before adding an Otherwise.");
+ }
+
+ [Fact]
+ public void OtherwiseThowsIfNoWhen()
+ {
+ Assert.Throws(() =>
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .Otherwise())
+ .Message
+ .ShouldBe("You must add a When before adding an Otherwise.");
+ }
+
+ [Fact]
+ public void WhenOtherwiseSimple()
+ {
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .When("7466B77C62134D72A9B37A7B4377EA1A")
+ .WhenProperty("BAEA343538474A71A3E9D9C01DABA1EE", "798AFBC1D5894E95BC7CD61D27B41CB6")
+ .OtherwiseProperty("BAEA343538474A71A3E9D9C01DABA1EE", "F08CB25B5C7C40AE88ADD98CC052DBD6")
+ .Xml
+ .ShouldBe(
+ @"
+
+
+
+ 798AFBC1D5894E95BC7CD61D27B41CB6
+
+
+
+
+ F08CB25B5C7C40AE88ADD98CC052DBD6
+
+
+
+",
+ StringCompareShould.IgnoreLineEndings);
+ }
+
+ [Fact]
+ public void WhenPropertyGroupThowsIfNoWhen()
+ {
+ Assert.Throws(() =>
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .WhenPropertyGroup())
+ .Message
+ .ShouldBe("You must add a When before adding a When PropertyGroup.");
+ }
+
+ [Fact]
+ public void WhenPropertyThowsIfNoWhen()
+ {
+ Assert.Throws(() =>
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .WhenProperty("A32ADB0D9F5D4BFAA927A39E1749A2A8", "A00D15F65FD34166BE03764D642ADD2A"))
+ .Message
+ .ShouldBe("You must add a When before adding a When PropertyGroup.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MSBuildProjectCreator.UnitTests/CreationTests.cs b/src/MSBuildProjectCreator.UnitTests/CreationTests.cs
deleted file mode 100644
index e2b844c..0000000
--- a/src/MSBuildProjectCreator.UnitTests/CreationTests.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) Jeff Kluge. All rights reserved.
-//
-// Licensed under the MIT license.
-
-using Microsoft.Build.Evaluation;
-using Shouldly;
-using System.Collections.Generic;
-using Xunit;
-
-namespace Microsoft.Build.Utilities.ProjectCreation.UnitTests
-{
- public class CreationTests : MSBuildTestBase
- {
- [Fact]
- public void GlobalPropertiesArePassedThrough()
- {
- ProjectCollection projectCollection = new ProjectCollection(new Dictionary
- {
- ["Property1"] = "5DFF776EBCFF4173B0E14160C2191402"
- });
-
- ProjectCreator creator = ProjectCreator.Create(projectCollection: projectCollection);
-
- creator.ProjectCollection.ShouldBe(projectCollection);
-
- creator.Project.ProjectCollection.ShouldBe(projectCollection);
-
- creator.Project.GlobalProperties.ShouldBe(projectCollection.GlobalProperties);
-
- creator.Project.GetPropertyValue("Property1").ShouldBe("5DFF776EBCFF4173B0E14160C2191402");
- }
- }
-}
diff --git a/src/MSBuildProjectCreator.UnitTests/ProjectTests.cs b/src/MSBuildProjectCreator.UnitTests/ProjectTests.cs
new file mode 100644
index 0000000..900baa6
--- /dev/null
+++ b/src/MSBuildProjectCreator.UnitTests/ProjectTests.cs
@@ -0,0 +1,100 @@
+// Copyright (c) Jeff Kluge. All rights reserved.
+//
+// Licensed under the MIT license.
+
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Exceptions;
+using Shouldly;
+using System;
+using System.Collections.Generic;
+using Xunit;
+
+namespace Microsoft.Build.Utilities.ProjectCreation.UnitTests
+{
+ public class ProjectTests : MSBuildTestBase
+ {
+ [Fact]
+ public void ProjectIsReEvaluated()
+ {
+ ProjectCollection projectCollection = new ProjectCollection();
+
+ ProjectCreator creator = ProjectCreator.Create(projectCollection: projectCollection);
+
+ creator.Project.GetPropertyValue("Property1").ShouldBe(String.Empty);
+
+ creator.Project.SetGlobalProperty("Property1", "8AD6F0530E774E468DBBD5B4143A1B1D");
+
+ creator.Project.GetPropertyValue("Property1").ShouldBe("8AD6F0530E774E468DBBD5B4143A1B1D");
+ }
+
+ [Fact]
+ public void ProjectWithGlobalProperties()
+ {
+ ProjectCollection projectCollection = new ProjectCollection(new Dictionary
+ {
+ ["Property1"] = "5DFF776EBCFF4173B0E14160C2191402"
+ });
+
+ ProjectCreator creator = ProjectCreator.Create(projectCollection: projectCollection);
+
+ creator.ProjectCollection.ShouldBeSameAs(projectCollection);
+
+ creator.Project.ProjectCollection.ShouldBeSameAs(projectCollection);
+
+ creator.Project.GlobalProperties.ShouldBe(projectCollection.GlobalProperties);
+
+ creator.Project.GetPropertyValue("Property1").ShouldBe("5DFF776EBCFF4173B0E14160C2191402");
+ }
+
+ [Fact]
+ public void TryGetProjectBuildOutput()
+ {
+ ProjectCreator.Create()
+ .Property("ImportDirectoryBuildTargets", "false")
+ .Import(@"$(MSBuildBinPath)\Microsoft.Common.targets")
+ .Import(@"$(MSBuildBinPath)\Microsoft.Common.targets")
+ .TryGetProject(out Project _, out BuildOutput buildOutput);
+
+ buildOutput.WarningEvents.ShouldHaveSingleItem().Code.ShouldBe("MSB4011");
+ }
+
+ [Fact]
+ public void TryGetProjectWithGlobalProperties()
+ {
+ ProjectCreator.Create()
+ .Property("Foo", "E82055CD4BBE40E58DF224A8734E75AC", setIfEmpty: true)
+ .TryGetProject(out Project project, new Dictionary
+ {
+ ["Foo"] = "CF8CBA9CEA034D2AB1704B11287579C8"
+ });
+
+ project.GetPropertyValue("Foo").ShouldBe("CF8CBA9CEA034D2AB1704B11287579C8");
+ }
+
+ [Fact]
+ public void TryGetProjectWithProjectCollection()
+ {
+ ProjectCollection expectedProjectCollection = new ProjectCollection(new Dictionary
+ {
+ ["Foo"] = "CF3478738DC04B3C9358FE0D23456BCD"
+ });
+
+ ProjectCreator.Create()
+ .Property("Foo", "4458994367D741719B24DE003EE4F541", setIfEmpty: true)
+ .TryGetProject(out Project project, projectCollection: expectedProjectCollection);
+
+ project.ProjectCollection.ShouldBeSameAs(expectedProjectCollection);
+
+ project.GetPropertyValue("Foo").ShouldBe("CF3478738DC04B3C9358FE0D23456BCD");
+ }
+
+ [Fact]
+ public void TryGetProjectWithToolsVersion()
+ {
+ Should.Throw(
+ () => ProjectCreator.Create().TryGetProject(out _, toolsVersion: "624491E368E24CE38F51D9D620685809"))
+ .Message
+ .ShouldStartWith("The tools version \"624491E368E24CE38F51D9D620685809\" is unrecognized. Available tools versions are");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MSBuildProjectCreator.UnitTests/SdkTests.cs b/src/MSBuildProjectCreator.UnitTests/SdkTests.cs
new file mode 100644
index 0000000..d3e8afb
--- /dev/null
+++ b/src/MSBuildProjectCreator.UnitTests/SdkTests.cs
@@ -0,0 +1,60 @@
+// Copyright (c) Jeff Kluge. All rights reserved.
+//
+// Licensed under the MIT license.
+
+using Microsoft.Build.Evaluation;
+using Shouldly;
+using Xunit;
+
+namespace Microsoft.Build.Utilities.ProjectCreation.UnitTests
+{
+ public class SdkTests : MSBuildTestBase
+ {
+ [Fact]
+ public void SdkComplex()
+ {
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .Sdk("3F86C1A37FFF45D698B5E496B0FF2096")
+ .Property("D1290ECCFEF44C8A98EF6CBCC4CB2D72", "E4BB6358D96B4C0B926C76D0F1C7BE89")
+ .Import("1A3971D93CF74C5EA7C952184159FD8C")
+ .Sdk("FC46B7002BC443D8836D3566D76D362D")
+ .Xml
+ .ShouldBe(
+ @"
+
+
+ E4BB6358D96B4C0B926C76D0F1C7BE89
+
+
+
+",
+ StringCompareShould.IgnoreLineEndings);
+ }
+
+ [Fact]
+ public void SdkSimple()
+ {
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .Sdk("8CFA5E8611DB4F12963FF495C43E015D")
+ .Xml
+ .ShouldBe(
+ @"
+
+",
+ StringCompareShould.IgnoreLineEndings);
+ }
+
+ [Fact]
+ public void SdkWithVersion()
+ {
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .Sdk("9104FA3137FB4581B337262DCBDBAD6A", "AA99A15EABF84EB2A6F23A9495A1D160")
+ .Xml
+ .ShouldBe(
+ @"
+
+",
+ StringCompareShould.IgnoreLineEndings);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MSBuildProjectCreator.UnitTests/TargetTests.cs b/src/MSBuildProjectCreator.UnitTests/TargetTests.cs
index b307822..8a97f88 100644
--- a/src/MSBuildProjectCreator.UnitTests/TargetTests.cs
+++ b/src/MSBuildProjectCreator.UnitTests/TargetTests.cs
@@ -119,6 +119,22 @@ public void TargetSimple()
.ShouldBe(
@"
+",
+ StringCompareShould.IgnoreLineEndings);
+ }
+
+ [Fact]
+ public void TargetWithOnError()
+ {
+ ProjectCreator.Create(projectFileOptions: NewProjectFileOptions.None)
+ .Target("80A389DEE56C4DFE9D81CCC9B176C09E")
+ .TargetOnError("CA51741A444D4B718A83E2364FE7DC98", "2F8BF0791F8F45AFB2F8D9338ECFDBA1")
+ .Xml
+ .ShouldBe(
+ @"
+
+
+
",
StringCompareShould.IgnoreLineEndings);
}
diff --git a/src/MSBuildProjectCreator/MSBuildAssemblyResolver.cs b/src/MSBuildProjectCreator/MSBuildAssemblyResolver.cs
index dd74bff..92ea993 100644
--- a/src/MSBuildProjectCreator/MSBuildAssemblyResolver.cs
+++ b/src/MSBuildProjectCreator/MSBuildAssemblyResolver.cs
@@ -4,7 +4,6 @@
using System;
using System.IO;
-using System.Linq;
using System.Reflection;
namespace Microsoft.Build.Utilities.ProjectCreation
@@ -14,11 +13,6 @@ namespace Microsoft.Build.Utilities.ProjectCreation
///
public static class MSBuildAssemblyResolver
{
- ///
- /// The MSBuild public key token b03f5f7f11d50a3a.
- ///
- private static readonly byte[] MicrosoftPublicKeyToken = { 0xB0, 0x3F, 0x5F, 0x7F, 0x11, 0xD5, 0x0A, 0x3A };
-
private static readonly Lazy MSBuildDirectoryLazy = new Lazy(
() =>
{
@@ -63,7 +57,7 @@ public static Assembly AssemblyResolve(object sender, ResolveEventArgs args)
{
AssemblyName assemblyName = new AssemblyName(args.Name);
- FileInfo fileInfo = new FileInfo(Path.Combine(MSBuildDirectoryLazy.Value, $"{assemblyName.Name}.dll"));
+ FileInfo fileInfo = new FileInfo(Path.Combine(MSBuildPath, $"{assemblyName.Name}.dll"));
if (!fileInfo.Exists)
{
diff --git a/src/MSBuildProjectCreator/ProjectCreator.Choose.cs b/src/MSBuildProjectCreator/ProjectCreator.Choose.cs
new file mode 100644
index 0000000..b827901
--- /dev/null
+++ b/src/MSBuildProjectCreator/ProjectCreator.Choose.cs
@@ -0,0 +1,288 @@
+// Copyright (c) Jeff Kluge. All rights reserved.
+//
+// Licensed under the MIT license.
+
+using Microsoft.Build.Construction;
+using Microsoft.Build.Utilities.ProjectCreation.Resources;
+using System.Collections.Generic;
+
+namespace Microsoft.Build.Utilities.ProjectCreation
+{
+ public partial class ProjectCreator
+ {
+ private ProjectChooseElement _lastChoose;
+ private ProjectItemGroupElement _lastOtherwiseItemGroup;
+ private ProjectPropertyGroupElement _lastOtherwisePropertyGroup;
+ private ProjectWhenElement _lastWhen;
+ private ProjectItemGroupElement _lastWhenItemGroup;
+ private ProjectPropertyGroupElement _lastWhenPropertyGroup;
+
+ ///
+ /// Gets the last <Choose /> element that was added.
+ ///
+ protected ProjectChooseElement LastChoose
+ {
+ get
+ {
+ if (_lastChoose == null)
+ {
+ Choose();
+ }
+
+ return _lastChoose;
+ }
+ }
+
+ ///
+ /// Adds a <Choose /> element to the current project.
+ ///
+ /// The current .
+ public ProjectCreator Choose()
+ {
+ _lastChoose = AddTopLevelElement(RootElement.CreateChooseElement());
+
+ _lastOtherwiseItemGroup = null;
+ _lastOtherwisePropertyGroup = null;
+ _lastWhen = null;
+ _lastWhenItemGroup = null;
+ _lastWhenPropertyGroup = null;
+
+ return this;
+ }
+
+ ///
+ /// Adds an <Otherwise /> element to the current project.
+ ///
+ /// The current .
+ /// A <When /> element has not been added
+ /// -or-
+ /// An <Otherwise /> has already been added to the current <Choose /> element.
+ public ProjectCreator Otherwise()
+ {
+ if (_lastWhen == null)
+ {
+ throw new ProjectCreatorException(Strings.ErrorOtherwiseRequresWhen);
+ }
+
+ if (_lastChoose.OtherwiseElement != null)
+ {
+ throw new ProjectCreatorException(Strings.ErrorOtherwiseCanOnlyBeSetOnce);
+ }
+
+ LastChoose.AppendChild(RootElement.CreateOtherwiseElement());
+
+ return this;
+ }
+
+ ///
+ /// Adds an <ItemGroup /> element to the current <Otherwise /> element.
+ ///
+ /// An optional condition to add to the item group.
+ /// The current .
+ /// A <When /> element has not been added.
+ public ProjectCreator OtherwiseItemGroup(string condition = null)
+ {
+ if (_lastWhen == null)
+ {
+ throw new ProjectCreatorException(Strings.ErrorOtherwiseRequresWhen);
+ }
+
+ if (_lastChoose.OtherwiseElement == null)
+ {
+ Otherwise();
+ }
+
+ _lastOtherwiseItemGroup = ItemGroup(_lastChoose.OtherwiseElement, condition);
+
+ return this;
+ }
+
+ ///
+ /// Adds an item to the current item group within the current <Otherwise /> element.
+ ///
+ /// The type of the item to add.
+ /// The file or wildcard to include in the list of items.
+ /// An optional file or wildcard to exclude from the list of items.
+ /// An optional containing metadata for the item.
+ /// An optional condition to add to the item.
+ /// The current .
+ /// A <When /> element has not been added.
+ public ProjectCreator OtherwiseItemInclude(
+ string itemType,
+ string include,
+ string exclude = null,
+ IDictionary metadata = null,
+ string condition = null)
+ {
+ if (_lastWhen == null)
+ {
+ throw new ProjectCreatorException(Strings.ErrorOtherwiseRequresWhen);
+ }
+
+ if (_lastOtherwiseItemGroup == null)
+ {
+ OtherwiseItemGroup();
+ }
+
+ return Item(
+ itemGroup: _lastOtherwiseItemGroup,
+ itemType: itemType,
+ include: include,
+ exclude: exclude,
+ metadata: metadata,
+ remove: null,
+ update: null,
+ condition: condition);
+ }
+
+ ///
+ /// Adds a property to the current <PropertyGroup /> element within the current <Otherwise /> element.
+ ///
+ /// The name of the property.
+ /// The unevaluated value of the property.
+ /// An optional condition to add to the property.
+ /// An optional value indicating whether or not a condition should be added that checks if the property has already been set.
+ /// The current .
+ ///
+ /// The parameter will add a condition such as " '$(Property)' == '' " which will only set the property if it has not already been set.
+ ///
+ public ProjectCreator OtherwiseProperty(string name, string unevaluatedValue, string condition = null, bool setIfEmpty = false)
+ {
+ if (_lastOtherwisePropertyGroup == null)
+ {
+ OtherwisePropertyGroup();
+ }
+
+ Property(_lastOtherwisePropertyGroup, name, unevaluatedValue, condition, setIfEmpty);
+
+ return this;
+ }
+
+ ///
+ /// Adds a <PropertyGroup /> element to the current <Otherwise /> element.
+ ///
+ /// An optional condition to add to the property group.
+ /// The current .
+ public ProjectCreator OtherwisePropertyGroup(string condition = null)
+ {
+ if (LastChoose.OtherwiseElement == null)
+ {
+ Otherwise();
+ }
+
+ _lastOtherwisePropertyGroup = PropertyGroup(LastChoose.OtherwiseElement, condition);
+
+ return this;
+ }
+
+ ///
+ /// Adds a <When /> element to the current <Choose /> element.
+ ///
+ /// An optional condition to add to the <When /> element.
+ /// The current .
+ public ProjectCreator When(string condition)
+ {
+ ProjectChooseElement lastChoose = LastChoose;
+
+ _lastWhen = RootElement.CreateWhenElement(condition);
+
+ lastChoose.AppendChild(_lastWhen);
+
+ _lastWhenPropertyGroup = null;
+ _lastWhenItemGroup = null;
+
+ return this;
+ }
+
+ ///
+ /// Adds an <ItemGroup /> element to the current <When /> element.
+ ///
+ /// An optional condition to add to the item group.
+ /// The current .
+ /// A <When /> element has not been added.
+ public ProjectCreator WhenItemGroup(string condition = null)
+ {
+ if (_lastWhen == null)
+ {
+ throw new ProjectCreatorException(Strings.ErrorWhenPropertyGroupRequiresWhen);
+ }
+
+ _lastWhenItemGroup = ItemGroup(_lastWhen, condition);
+
+ return this;
+ }
+
+ ///
+ /// Adds an item to the current item group within the current <When /> element.
+ ///
+ /// The type of the item to add.
+ /// The file or wildcard to include in the list of items.
+ /// An optional file or wildcard to exclude from the list of items.
+ /// An optional containing metadata for the item.
+ /// An optional condition to add to the item.
+ /// The current .
+ public ProjectCreator WhenItemInclude(
+ string itemType,
+ string include,
+ string exclude = null,
+ IDictionary metadata = null,
+ string condition = null)
+ {
+ if (_lastWhenItemGroup == null)
+ {
+ WhenItemGroup();
+ }
+
+ return Item(
+ itemGroup: _lastWhenItemGroup,
+ itemType: itemType,
+ include: include,
+ exclude: exclude,
+ metadata: metadata,
+ remove: null,
+ update: null,
+ condition: condition);
+ }
+
+ ///
+ /// Adds a property to the current <PropertyGroup /> element within the current <When /> element.
+ ///
+ /// The name of the property.
+ /// The unevaluated value of the property.
+ /// An optional condition to add to the property.
+ /// An optional value indicating whether or not a condition should be added that checks if the property has already been set.
+ /// The current .
+ ///
+ /// The parameter will add a condition such as " '$(Property)' == '' " which will only set the property if it has not already been set.
+ ///
+ public ProjectCreator WhenProperty(string name, string unevaluatedValue, string condition = null, bool setIfEmpty = false)
+ {
+ if (_lastWhenPropertyGroup == null)
+ {
+ WhenPropertyGroup();
+ }
+
+ Property(_lastWhenPropertyGroup, name, unevaluatedValue, condition, setIfEmpty);
+
+ return this;
+ }
+
+ ///
+ /// Adds a <PropertyGroup /> element to the current <When /> element.
+ ///
+ /// An optional condition to add to the property group.
+ /// The current .
+ /// A <When /> element has not been added.
+ public ProjectCreator WhenPropertyGroup(string condition = null)
+ {
+ if (_lastWhen == null)
+ {
+ throw new ProjectCreatorException(Strings.ErrorWhenPropertyGroupRequiresWhen);
+ }
+
+ _lastWhenPropertyGroup = PropertyGroup(_lastWhen, condition);
+
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MSBuildProjectCreator/ProjectCreator.Conversions.cs b/src/MSBuildProjectCreator/ProjectCreator.Conversions.cs
index 9a0e476..2dd81f2 100644
--- a/src/MSBuildProjectCreator/ProjectCreator.Conversions.cs
+++ b/src/MSBuildProjectCreator/ProjectCreator.Conversions.cs
@@ -4,6 +4,8 @@
using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
+using System;
+using System.Xml.Linq;
namespace Microsoft.Build.Utilities.ProjectCreation
{
@@ -18,6 +20,15 @@ public static implicit operator Project(ProjectCreator creator)
return creator?.Project;
}
+ ///
+ /// Defines an implicit conversion of a to a .
+ ///
+ /// A to convert.
+ public static implicit operator ProjectCollection(ProjectCreator creator)
+ {
+ return creator.ProjectCollection;
+ }
+
///
/// Defines an implicit conversion of a to a .
///
@@ -26,5 +37,23 @@ public static implicit operator ProjectRootElement(ProjectCreator creator)
{
return creator.RootElement;
}
+
+ ///
+ /// Defines an implicit conversion of a to a .
+ ///
+ /// A to convert.
+ public static implicit operator String(ProjectCreator creator)
+ {
+ return creator.FullPath;
+ }
+
+ ///
+ /// Defines an implicit conversion of a to an .
+ ///
+ /// A to convert.
+ public static implicit operator XDocument(ProjectCreator creator)
+ {
+ return XDocument.Parse(creator.Xml);
+ }
}
}
\ No newline at end of file
diff --git a/src/MSBuildProjectCreator/ProjectCreator.Imports.cs b/src/MSBuildProjectCreator/ProjectCreator.Imports.cs
index 501210d..a018a73 100644
--- a/src/MSBuildProjectCreator/ProjectCreator.Imports.cs
+++ b/src/MSBuildProjectCreator/ProjectCreator.Imports.cs
@@ -88,7 +88,7 @@ public ProjectCreator Import(ProjectRootElement projectRootElement, string condi
/// The current .
public ProjectCreator ImportSdk(string project, string name, string version = null, string condition = null)
{
- return Import(project, condition, name, version, false);
+ return Import(project, condition, name, version);
}
}
}
\ No newline at end of file
diff --git a/src/MSBuildProjectCreator/ProjectCreator.ItemGroups.cs b/src/MSBuildProjectCreator/ProjectCreator.ItemGroups.cs
index 3736fc6..e499e11 100644
--- a/src/MSBuildProjectCreator/ProjectCreator.ItemGroups.cs
+++ b/src/MSBuildProjectCreator/ProjectCreator.ItemGroups.cs
@@ -42,5 +42,22 @@ public ProjectCreator ItemGroup(string condition = null)
return this;
}
+
+ ///
+ /// Adds an <ItemGroup /> element to the specifed parent.
+ ///
+ /// A parent to add the item group to.
+ /// An optional condition to add to the item group.
+ /// The current .
+ protected ProjectItemGroupElement ItemGroup(ProjectElementContainer parent, string condition = null)
+ {
+ ProjectItemGroupElement itemGroup = RootElement.CreateItemGroupElement();
+
+ parent.AppendChild(itemGroup);
+
+ itemGroup.Condition = condition;
+
+ return itemGroup;
+ }
}
}
\ No newline at end of file
diff --git a/src/MSBuildProjectCreator/ProjectCreator.Linq.cs b/src/MSBuildProjectCreator/ProjectCreator.Linq.cs
index fb70c56..63d5ff2 100644
--- a/src/MSBuildProjectCreator/ProjectCreator.Linq.cs
+++ b/src/MSBuildProjectCreator/ProjectCreator.Linq.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
-using System.Text;
namespace Microsoft.Build.Utilities.ProjectCreation
{
diff --git a/src/MSBuildProjectCreator/ProjectCreator.Project.cs b/src/MSBuildProjectCreator/ProjectCreator.Project.cs
new file mode 100644
index 0000000..6cd8523
--- /dev/null
+++ b/src/MSBuildProjectCreator/ProjectCreator.Project.cs
@@ -0,0 +1,96 @@
+// Copyright (c) Jeff Kluge. All rights reserved.
+//
+// Licensed under the MIT license.
+
+using Microsoft.Build.Evaluation;
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.Build.Utilities.ProjectCreation
+{
+ public partial class ProjectCreator
+ {
+ ///
+ /// Stores the instance used to create a object lazily.
+ ///
+ private Project _project;
+
+ ///
+ /// Gets the instance for the current project. The project is re-evaluated if necessary every time this property is accessed.
+ ///
+ public Project Project
+ {
+ get
+ {
+ if (_project == null)
+ {
+ TryGetProject(out _project, ProjectCollection.GlobalProperties, String.IsNullOrEmpty(RootElement.ToolsVersion) ? null : RootElement.ToolsVersion, ProjectCollection);
+ }
+
+ _project.ReevaluateIfNecessary();
+
+ return _project;
+ }
+ }
+
+ ///
+ /// Gets a instance from the current project.
+ ///
+ /// Receives the instance.
+ /// Optional containing global properties.
+ /// Optional tools version.
+ /// Optional to use. Defaults to ProjectCollection.GlobalProjectCollection.
+ /// Optional to use. Defaults to .
+ /// The current .
+ public ProjectCreator TryGetProject(
+ out Project project,
+ IDictionary globalProperties = null,
+ string toolsVersion = null,
+ ProjectCollection projectCollection = null,
+ ProjectLoadSettings projectLoadSettings = ProjectLoadSettings.Default)
+ {
+ project = new Project(
+ RootElement,
+ globalProperties ?? projectCollection?.GlobalProperties,
+ toolsVersion,
+ projectCollection ?? ProjectCollection.GlobalProjectCollection,
+ projectLoadSettings);
+
+ return this;
+ }
+
+ ///
+ /// Gets a instance from the current project.
+ ///
+ /// Receives the instance.
+ /// Receives instance.
+ /// Optional containing global properties.
+ /// Optional tools version.
+ /// Optional to use. Defaults to ProjectCollection.GlobalProjectCollection.
+ /// Optional to use. Defaults to .
+ /// The current .
+ public ProjectCreator TryGetProject(
+ out Project project,
+ out BuildOutput buildOutput,
+ IDictionary globalProperties = null,
+ string toolsVersion = null,
+ ProjectCollection projectCollection = null,
+ ProjectLoadSettings projectLoadSettings = ProjectLoadSettings.Default)
+ {
+ buildOutput = BuildOutput.Create();
+
+ projectCollection = projectCollection ?? ProjectCollection ?? new ProjectCollection();
+
+ projectCollection.RegisterLogger(buildOutput);
+
+ project = new Project(
+ RootElement,
+ globalProperties ?? projectCollection.GlobalProperties,
+ toolsVersion,
+ projectCollection,
+ projectLoadSettings);
+
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MSBuildProjectCreator/ProjectCreator.PropertyGroups.cs b/src/MSBuildProjectCreator/ProjectCreator.PropertyGroups.cs
index 55c0929..910a240 100644
--- a/src/MSBuildProjectCreator/ProjectCreator.PropertyGroups.cs
+++ b/src/MSBuildProjectCreator/ProjectCreator.PropertyGroups.cs
@@ -42,5 +42,22 @@ public ProjectCreator PropertyGroup(string condition = null)
return this;
}
+
+ ///
+ /// Adds a <PropertyGroup /> element to the specified .
+ ///
+ /// The parent to add the property group to.
+ /// An optional condition to add to the property group.
+ /// The that was added.
+ protected ProjectPropertyGroupElement PropertyGroup(ProjectElementContainer parent, string condition = null)
+ {
+ ProjectPropertyGroupElement propertyGroup = RootElement.CreatePropertyGroupElement();
+
+ parent.AppendChild(propertyGroup);
+
+ propertyGroup.Condition = condition;
+
+ return propertyGroup;
+ }
}
}
\ No newline at end of file
diff --git a/src/MSBuildProjectCreator/ProjectCreator.Sdk.cs b/src/MSBuildProjectCreator/ProjectCreator.Sdk.cs
new file mode 100644
index 0000000..ab481f0
--- /dev/null
+++ b/src/MSBuildProjectCreator/ProjectCreator.Sdk.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Jeff Kluge. All rights reserved.
+//
+// Licensed under the MIT license.
+
+namespace Microsoft.Build.Utilities.ProjectCreation
+{
+ public partial class ProjectCreator
+ {
+ ///
+ /// Adds an <Sdk /> element to the current project.
+ ///
+ /// The name of the SDK.
+ /// An optional version of the SDK.
+ /// The current .
+ public ProjectCreator Sdk(string name, string version = null)
+ {
+ AddTopLevelElement(RootElement.CreateProjectSdkElement(name, version));
+
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/MSBuildProjectCreator/ProjectCreator.Targets.cs b/src/MSBuildProjectCreator/ProjectCreator.Targets.cs
index e9a0243..7ae2237 100644
--- a/src/MSBuildProjectCreator/ProjectCreator.Targets.cs
+++ b/src/MSBuildProjectCreator/ProjectCreator.Targets.cs
@@ -90,9 +90,7 @@ public ProjectCreator Target(
/// The current .
public ProjectCreator TargetItemGroup(string condition = null)
{
- _lastTargetItemGroup = LastTarget.AddItemGroup();
-
- _lastTargetItemGroup.Condition = condition;
+ _lastTargetItemGroup = ItemGroup(LastTarget, condition);
return this;
}
@@ -129,6 +127,23 @@ public ProjectCreator TargetItemInclude(
condition: condition);
}
+ ///
+ /// Adds an <OnError /> element to the current target.
+ ///
+ /// The targets to execute if a task fails. Separate multiple targets with semicolons. Multiple targets are executed in the order specified.
+ /// Condition to be evaluated.
+ /// The current .
+ public ProjectCreator TargetOnError(string executeTargets, string condition = null)
+ {
+ ProjectOnErrorElement onErrorElement = RootElement.CreateOnErrorElement(executeTargets);
+
+ LastTarget.AppendChild(onErrorElement);
+
+ onErrorElement.Condition = condition;
+
+ return this;
+ }
+
///
/// Adds a property element to the current <PropertyGroup /> of the current target. A property group is automatically added if necessary.
///
@@ -157,11 +172,7 @@ public ProjectCreator TargetProperty(string name, string unevaluatedValue, strin
/// The current .
public ProjectCreator TargetPropertyGroup(string condition = null)
{
- _lastTargetPropertyGroup = RootElement.CreatePropertyGroupElement();
-
- LastTarget.AppendChild(_lastTargetPropertyGroup);
-
- _lastTargetPropertyGroup.Condition = condition;
+ _lastTargetPropertyGroup = PropertyGroup(LastTarget, condition);
return this;
}
diff --git a/src/MSBuildProjectCreator/ProjectCreator.cs b/src/MSBuildProjectCreator/ProjectCreator.cs
index 86b397c..ae7de14 100644
--- a/src/MSBuildProjectCreator/ProjectCreator.cs
+++ b/src/MSBuildProjectCreator/ProjectCreator.cs
@@ -17,11 +17,6 @@ namespace Microsoft.Build.Utilities.ProjectCreation
///
public partial class ProjectCreator
{
- ///
- /// Stores the instance used to create a object lazily.
- ///
- private readonly Lazy _projectLazy;
-
///
/// Stores the last top-level element added to the project XML.
///
@@ -34,14 +29,6 @@ public partial class ProjectCreator
private ProjectCreator(ProjectRootElement rootElement)
{
RootElement = rootElement;
-
- _projectLazy = new Lazy(
- () => new Project(
- RootElement,
- ProjectCollection.GlobalProperties,
- String.IsNullOrEmpty(RootElement.ToolsVersion) ? null : RootElement.ToolsVersion,
- ProjectCollection),
- isThreadSafe: true);
}
///
@@ -49,19 +36,6 @@ private ProjectCreator(ProjectRootElement rootElement)
///
public string FullPath => RootElement.FullPath;
- ///
- /// Gets the instance for the current project. The project is re-evaluated if necessary every time this property is accessed.
- ///
- public Project Project
- {
- get
- {
- _projectLazy.Value.ReevaluateIfNecessary();
-
- return _projectLazy.Value;
- }
- }
-
///
/// Gets the for the current project.
///
diff --git a/src/MSBuildProjectCreator/Resources/Strings.Designer.cs b/src/MSBuildProjectCreator/Resources/Strings.Designer.cs
index 392692c..ef824ef 100644
--- a/src/MSBuildProjectCreator/Resources/Strings.Designer.cs
+++ b/src/MSBuildProjectCreator/Resources/Strings.Designer.cs
@@ -10,7 +10,6 @@
namespace Microsoft.Build.Utilities.ProjectCreation.Resources {
using System;
- using System.Reflection;
///
@@ -40,7 +39,7 @@ internal Strings() {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Build.Utilities.ProjectCreation.Resources.Strings", typeof(Strings).GetTypeInfo().Assembly);
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Build.Utilities.ProjectCreation.Resources.Strings", typeof(Strings).Assembly);
resourceMan = temp;
}
return resourceMan;
@@ -61,6 +60,24 @@ internal Strings() {
}
}
+ ///
+ /// Looks up a localized string similar to You can only add one Otherwise to a Choose..
+ ///
+ internal static string ErrorOtherwiseCanOnlyBeSetOnce {
+ get {
+ return ResourceManager.GetString("ErrorOtherwiseCanOnlyBeSetOnce", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to You must add a When before adding an Otherwise..
+ ///
+ internal static string ErrorOtherwiseRequresWhen {
+ get {
+ return ResourceManager.GetString("ErrorOtherwiseRequresWhen", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to You must add a Task by before you can add an output item..
///
@@ -105,5 +122,23 @@ internal static string ErrorUsingTaskParameterRequiresUsingTask {
return ResourceManager.GetString("ErrorUsingTaskParameterRequiresUsingTask", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to You must add a When before adding a When ItemGroup..
+ ///
+ internal static string ErrorWhenItemGroupRequiresWhen {
+ get {
+ return ResourceManager.GetString("ErrorWhenItemGroupRequiresWhen", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to You must add a When before adding a When PropertyGroup..
+ ///
+ internal static string ErrorWhenPropertyGroupRequiresWhen {
+ get {
+ return ResourceManager.GetString("ErrorWhenPropertyGroupRequiresWhen", resourceCulture);
+ }
+ }
}
}
diff --git a/src/MSBuildProjectCreator/Resources/Strings.resx b/src/MSBuildProjectCreator/Resources/Strings.resx
index c85ec7d..fe9b42e 100644
--- a/src/MSBuildProjectCreator/Resources/Strings.resx
+++ b/src/MSBuildProjectCreator/Resources/Strings.resx
@@ -117,7 +117,12 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
+ You can only add one Otherwise to a Choose.
+
+
+ You must add a When before adding an Otherwise.
+
You must add a Task by before you can add an output item.
@@ -133,4 +138,10 @@
You must add a UsingTask before adding a UsingTask parameter.
+
+ You must add a When before adding a When ItemGroup.
+
+
+ You must add a When before adding a When PropertyGroup.
+
\ No newline at end of file
diff --git a/version.json b/version.json
index b36402d..3bed904 100644
--- a/version.json
+++ b/version.json
@@ -10,7 +10,7 @@
"cloudBuild": {
"setVersionVariables": true,
"buildNumber": {
- "enabled": false,
+ "enabled": true,
"includeCommitId": {
"when": "nonPublicReleaseOnly",
"where": "buildMetadata"