diff --git a/src/extensions/try-convert/MSBuild.Abstractions/MSBuildConversionWorkspace.cs b/src/extensions/try-convert/MSBuild.Abstractions/MSBuildConversionWorkspace.cs
index 0cb39601f..c976e6a5b 100644
--- a/src/extensions/try-convert/MSBuild.Abstractions/MSBuildConversionWorkspace.cs
+++ b/src/extensions/try-convert/MSBuild.Abstractions/MSBuildConversionWorkspace.cs
@@ -249,6 +249,7 @@ private bool IsSupportedOutputType(ProjectOutputType type) =>
ProjectOutputType.Library => true,
ProjectOutputType.WinExe => true,
ProjectOutputType.AppContainerExe => true,
+ ProjectOutputType.WinMdObj => true,
_ => false
};
@@ -295,6 +296,10 @@ private ProjectOutputType GetProjectOutputType(IProjectRootElement root, Project
{
return ProjectOutputType.AppContainerExe;
}
+ else if (ProjectPropertyHelpers.IsWinMdObjProjectType(outputTypeNode))
+ {
+ return ProjectOutputType.WinMdObj;
+ }
else
{
return ProjectOutputType.Other;
diff --git a/src/extensions/try-convert/MSBuild.Abstractions/ProjectOutputType.cs b/src/extensions/try-convert/MSBuild.Abstractions/ProjectOutputType.cs
index 795d1db67..2d72d2bbe 100644
--- a/src/extensions/try-convert/MSBuild.Abstractions/ProjectOutputType.cs
+++ b/src/extensions/try-convert/MSBuild.Abstractions/ProjectOutputType.cs
@@ -16,6 +16,7 @@ public enum ProjectOutputType
Exe,
WinExe,
AppContainerExe,
+ WinMdObj,
Other,
None
}
diff --git a/src/extensions/try-convert/MSBuild.Abstractions/ProjectPropertyHelpers.cs b/src/extensions/try-convert/MSBuild.Abstractions/ProjectPropertyHelpers.cs
index 5c049641d..600ed3853 100644
--- a/src/extensions/try-convert/MSBuild.Abstractions/ProjectPropertyHelpers.cs
+++ b/src/extensions/try-convert/MSBuild.Abstractions/ProjectPropertyHelpers.cs
@@ -188,6 +188,13 @@ public static bool IsWinExeOutputType(ProjectPropertyElement prop) =>
prop.ElementName.Equals(MSBuildFacts.OutputTypeNodeName, StringComparison.OrdinalIgnoreCase)
&& prop.Value.Equals(MSBuildFacts.WinExeOutputType, StringComparison.OrdinalIgnoreCase);
+ ///
+ /// Checks if an OutputType node is WinMdObj.
+ ///
+ public static bool IsWinMdObjProjectType(ProjectPropertyElement prop) =>
+ prop.ElementName.Equals(MSBuildFacts.OutputTypeNodeName, StringComparison.OrdinalIgnoreCase)
+ && prop.Value.Equals(MSBuildFacts.WinMdObjOutputType, StringComparison.OrdinalIgnoreCase);
+
public static bool IsVisualBasicProject(ProjectPropertyElement prop) =>
IsProjectTypeGuidsNode(prop) && prop.Value.Split(';').Any(guidString => Guid.Parse(guidString) == MSBuildFacts.LanguageProjectTypeVisualBasic);
diff --git a/src/extensions/try-convert/MSBuild.Conversion.Facts/MSBuildFacts.cs b/src/extensions/try-convert/MSBuild.Conversion.Facts/MSBuildFacts.cs
index ffd10c0a2..22042b255 100644
--- a/src/extensions/try-convert/MSBuild.Conversion.Facts/MSBuildFacts.cs
+++ b/src/extensions/try-convert/MSBuild.Conversion.Facts/MSBuildFacts.cs
@@ -288,6 +288,7 @@ public static class MSBuildFacts
public const string ExeOutputType = "Exe";
public const string WinExeOutputType = "WinExe";
public const string AppContainerExeOutputType = "AppContainerExe";
+ public const string WinMdObjOutputType = "winmdobj";
public const string NuGetPackageImportStampNodeName = "NuGetPackageImportStamp";
public const string ReferencePathNodeName = "ReferencePath";
public const string LegacyTargetFrameworkPropertyNodeName = "TargetFrameworkIdentifier";
@@ -311,5 +312,7 @@ public static class MSBuildFacts
public const string TargetPlatformIdentifierNodeName = "TargetPlatformIdentifier";
public const string UapValue = "UAP";
public const string TargetPlatformVersionNodeName = "TargetPlatformVersion";
+ public const string CsWinRTComponentName = "CsWinRTComponent";
+ public static readonly (string Name, string Version) CsWinRTPackageReference = (Name: "Microsoft.Windows.CsWinRT", Version: "1.6.4");
}
}
diff --git a/src/extensions/try-convert/MSBuild.Conversion.Project/Converter.cs b/src/extensions/try-convert/MSBuild.Conversion.Project/Converter.cs
index c6b18b00d..b98dae548 100644
--- a/src/extensions/try-convert/MSBuild.Conversion.Project/Converter.cs
+++ b/src/extensions/try-convert/MSBuild.Conversion.Project/Converter.cs
@@ -46,6 +46,7 @@ public void Convert(string outputPath)
// Now we can convert the project over
.ChangeImportsAndAddSdkAttribute(_sdkBaselineProject, _forceRemoveCustomImports)
+ .AddCsWinRTReferenceAndComponentProperty(_sdkBaselineProject)
.UpdateOutputTypeProperty(_sdkBaselineProject)
.RemoveDefaultedProperties(_sdkBaselineProject, _differs)
.RemoveUnnecessaryPropertiesNotInSDKByDefault(_sdkBaselineProject.ProjectStyle)
diff --git a/src/extensions/try-convert/MSBuild.Conversion.Project/ProjectRootElementExtensionsForConversion.cs b/src/extensions/try-convert/MSBuild.Conversion.Project/ProjectRootElementExtensionsForConversion.cs
index 56987f280..5b04ea63f 100644
--- a/src/extensions/try-convert/MSBuild.Conversion.Project/ProjectRootElementExtensionsForConversion.cs
+++ b/src/extensions/try-convert/MSBuild.Conversion.Project/ProjectRootElementExtensionsForConversion.cs
@@ -68,6 +68,21 @@ public static IProjectRootElement ChangeImportsAndAddSdkAttribute(this IProjectR
return projectRootElement;
}
+ public static IProjectRootElement AddCsWinRTReferenceAndComponentProperty(this IProjectRootElement projectRootElement, BaselineProject baselineProject)
+ {
+ if (baselineProject.OutputType == ProjectOutputType.WinMdObj)
+ {
+ var topLevelPropGroup = MSBuildHelpers.GetOrCreateTopLevelPropertyGroup(baselineProject, projectRootElement);
+ topLevelPropGroup.AddProperty(MSBuildFacts.CsWinRTComponentName, "true");
+
+ var packageReferenceItemGroup = projectRootElement.ItemGroups.Where(ig => ig.Items.Any(i => i.ItemType == MSBuildFacts.MSBuildPackageReferenceName))
+ .FirstOrDefault() ?? projectRootElement.AddItemGroup();
+ AddPackageReferenceElement(packageReferenceItemGroup, MSBuildFacts.CsWinRTPackageReference.Name, MSBuildFacts.CsWinRTPackageReference.Version);
+ }
+
+ return projectRootElement;
+ }
+
public static IProjectRootElement UpdateOutputTypeProperty(this IProjectRootElement projectRootElement, BaselineProject baselineProject)
{
var outputTypeNode = projectRootElement.GetOutputTypeNode();
@@ -79,6 +94,7 @@ public static IProjectRootElement UpdateOutputTypeProperty(this IProjectRootElem
ProjectOutputType.Library => MSBuildFacts.LibraryOutputType,
ProjectOutputType.WinExe => MSBuildFacts.WinExeOutputType,
ProjectOutputType.AppContainerExe => MSBuildFacts.WinExeOutputType,
+ ProjectOutputType.WinMdObj => MSBuildFacts.LibraryOutputType,
_ => throw new InvalidOperationException("Unsupported output type: " + baselineProject.OutputType)
};
}
diff --git a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/Utils/IProjectExtensions.cs b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/Utils/IProjectExtensions.cs
new file mode 100644
index 000000000..c9e0a6259
--- /dev/null
+++ b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/Utils/IProjectExtensions.cs
@@ -0,0 +1,15 @@
+// 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.Linq;
+using System.Text;
+
+namespace Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade.Utils
+{
+ public static class IProjectExtensions
+ {
+ public static IEnumerable AllProjectReferences(this IProject project) => project.GetRoslynProject().AllProjectReferences.Select(projRef => projRef.ProjectId.ToString());
+ }
+}
diff --git a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/UWPToWinUIHelpers.cs b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/Utils/SyntaxNodeExtensions.cs
similarity index 92%
rename from src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/UWPToWinUIHelpers.cs
rename to src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/Utils/SyntaxNodeExtensions.cs
index 7bdf103d6..f7bfa1c16 100644
--- a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/UWPToWinUIHelpers.cs
+++ b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/Utils/SyntaxNodeExtensions.cs
@@ -9,9 +9,9 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
-namespace Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade
+namespace Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade.Utils
{
- internal static class UWPToWinUIHelpers
+ internal static class SyntaxNodeExtensions
{
public static IEnumerable GetAllImportedNamespaces(this SyntaxNode node)
{
diff --git a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIAppWIndowAnalyzer.cs b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIAppWIndowAnalyzer.cs
index ae4409be9..72ca770ca 100644
--- a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIAppWIndowAnalyzer.cs
+++ b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIAppWIndowAnalyzer.cs
@@ -10,8 +10,8 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade;
using Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade.Abstractions;
+using Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade.Utils;
namespace Microsoft.DotNet.UpgradeAssistant.Extensions.Windows
{
diff --git a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIInteropAnalyzer.cs b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIInteropAnalyzer.cs
index 4d1924067..3ddcc4eb9 100644
--- a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIInteropAnalyzer.cs
+++ b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIInteropAnalyzer.cs
@@ -10,7 +10,7 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade;
+using Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade.Utils;
namespace Microsoft.DotNet.UpgradeAssistant.Extensions.Windows
{
diff --git a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIMRTResourceManagerAnalyzer.cs b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIMRTResourceManagerAnalyzer.cs
index ed93572f2..a07b58dc0 100644
--- a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIMRTResourceManagerAnalyzer.cs
+++ b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIMRTResourceManagerAnalyzer.cs
@@ -10,7 +10,7 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
-using Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade;
+using Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade.Utils;
namespace Microsoft.DotNet.UpgradeAssistant.Extensions.Windows
{
diff --git a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIPropertiesUpdater.cs b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIPropertiesUpdater.cs
index 693e4bb67..9852d6c18 100644
--- a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIPropertiesUpdater.cs
+++ b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIPropertiesUpdater.cs
@@ -4,10 +4,13 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Globalization;
using System.IO;
+using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade.Utils;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@@ -18,6 +21,12 @@ public class WinUIPropertiesUpdater : IUpdater
{
public const string RuleID = "UA302";
+ private const string CsWinRTLogMessageFormat = "A CsWinRTIncludes property with value {0} has been added to specify the namespace of the referenced vcxproj component to project..\n" +
+ "If your project assembly name differs from {0}, update this value with the assembly name.\n" +
+ "Read more about C#/WinRT here: https://docs.microsoft.com/en-us/windows/apps/develop/platform/csharp-winrt/";
+
+ private const string CsWinRTIncludesProperty = "CsWinRTIncludes";
+
public string Id => typeof(WinUIPropertiesUpdater).FullName;
public string Title => "Update WinUI Project Properties";
@@ -69,6 +78,19 @@ public async Task ApplyAsync(IUpgradeContext context, ImmutableA
}
}
+ foreach (var projRef in project.AllProjectReferences())
+ {
+ if (projRef.Contains(".vcxproj"))
+ {
+ var projectName = ParseProjectNameWithExtension(projRef, ".vcxproj");
+ var csWinRTIncludesValue = projectFile.GetPropertyValue(CsWinRTIncludesProperty) ?? string.Empty;
+ var delimiter = csWinRTIncludesValue.Trim().Length == 0 || csWinRTIncludesValue.EndsWith(";") ? string.Empty : ";";
+ projectFile.SetPropertyValue(CsWinRTIncludesProperty, $"{csWinRTIncludesValue}{delimiter}{projectName}");
+
+ _logger.LogInformation(string.Format(CsWinRTLogMessageFormat, projectName));
+ }
+ }
+
projectFile.AddItem(new ProjectItemDescriptor(ProjectItemType.Compile) { Remove = "App.xaml.old.cs" });
projectFile.AddItem(new ProjectItemDescriptor(ProjectItemType.None) { Include = "App.xaml.old.cs" });
projectFile.RemoveItem(new ProjectItemDescriptor(ProjectItemType.Content) { Include = "Properties\\Default.rd.xml" });
@@ -85,6 +107,25 @@ public async Task ApplyAsync(IUpgradeContext context, ImmutableA
new List());
}
+ /*
+ This function parses the project name from projectReference string which includes the file path, project id and more text.
+ It does so by finding the position of ".vcxproj" in the string and then reading the name backwards character by character
+ until the first non-alphanumeric character.
+ */
+ private string ParseProjectNameWithExtension(string projectReference, string extension)
+ {
+ var index = projectReference.IndexOf(".vcxproj");
+ index--;
+ StringBuilder sb = new StringBuilder();
+ while (index > -1 && char.IsLetterOrDigit(projectReference[index]))
+ {
+ sb.Append(projectReference[index]);
+ index--;
+ }
+
+ return new string(sb.ToString().Reverse().ToArray());
+ }
+
public async Task IsApplicableAsync(IUpgradeContext context, ImmutableArray inputs, CancellationToken token)
{
await Task.Yield();
diff --git a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIReferenceAnalyzer.cs b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIReferenceAnalyzer.cs
index dcbe761c1..ae96d0a46 100644
--- a/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIReferenceAnalyzer.cs
+++ b/src/extensions/windows/Microsoft.DotNet.UpgradeAssistant.Extensions.Windows/UWPtoWinAppSDKUpgrade/WinUIReferenceAnalyzer.cs
@@ -6,9 +6,11 @@
using System.Collections.Immutable;
using System.Linq;
using System.Text;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.DotNet.UpgradeAssistant.Dependencies;
+using Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade.Utils;
using Microsoft.Extensions.Logging;
namespace Microsoft.DotNet.UpgradeAssistant.Extensions.Windows.UWPtoWinAppSDKUpgrade
@@ -18,6 +20,9 @@ internal class WinUIReferenceAnalyzer : IDependencyAnalyzer
{
public string Name => "Windows App SDK package analysis";
+ private const string CsWinRTPackageName = "Microsoft.Windows.CsWinRT";
+ private const string CsWinRTVersion = "1.6.4";
+
private readonly IPackageLoader _packageLoader;
private readonly ILogger _logger;
@@ -34,6 +39,13 @@ public async Task AnalyzeAsync(IProject project, IDependencyAnalysisState state,
return;
}
+ if (project.AllProjectReferences().Any(id => id.Contains(".vcxproj")))
+ {
+ var newPackage = new NuGetReference(CsWinRTPackageName, CsWinRTVersion);
+ state.Packages.Add(newPackage,
+ new OperationDetails() { Risk = BuildBreakRisk.Medium, Details = ImmutableList.Create(newPackage.Name) });
+ }
+
foreach (var package in state.Packages)
{
if (package.Name.StartsWith("Microsoft.Toolkit", StringComparison.Ordinal))