diff --git a/src/Uno.Sdk/Sdk/Sdk.targets b/src/Uno.Sdk/Sdk/Sdk.targets
index e84c5c144834..dd09b86e679c 100644
--- a/src/Uno.Sdk/Sdk/Sdk.targets
+++ b/src/Uno.Sdk/Sdk/Sdk.targets
@@ -10,10 +10,6 @@ Copyright (C) Uno Platform Inc. All rights reserved.
-->
-
- $(AfterMicrosoftNETSdkTargets);$(_UnoSdkTargetsDirectory)Uno.Sdk.After.targets
-
-
@@ -28,5 +24,8 @@ Copyright (C) Uno Platform Inc. All rights reserved.
+
+
+
diff --git a/src/Uno.Sdk/targets/Uno.Sdk.After.targets b/src/Uno.Sdk/targets/Uno.Sdk.After.targets
index f77ca91a07df..860a705f80df 100644
--- a/src/Uno.Sdk/targets/Uno.Sdk.After.targets
+++ b/src/Uno.Sdk/targets/Uno.Sdk.After.targets
@@ -12,4 +12,43 @@
+
+
+
+ <_UnoTargetFrameworkCount>$(TargetFrameworks.Split(';', System.StringSplitOptions.RemoveEmptyEntries).Length)
+ <_UnoFirstOriginalTargetFramework>$(TargetFrameworks.Split(';', System.StringSplitOptions.RemoveEmptyEntries)[0])
+
+
+
+
+ <_UnoTargetFrameworksWasmFiltered>$(TargetFrameworks.Replace($(ActiveDebugFramework),''))
+
+ $([MSBuild]::Unescape('$(ActiveDebugFramework);$(_UnoTargetFrameworksWasmFiltered)'))
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Uno.UI.RemoteControl.VS/DebuggerHelper/ProfilesObserver.cs b/src/Uno.UI.RemoteControl.VS/DebuggerHelper/ProfilesObserver.cs
index 6c925557c8ce..7e26eb104f57 100644
--- a/src/Uno.UI.RemoteControl.VS/DebuggerHelper/ProfilesObserver.cs
+++ b/src/Uno.UI.RemoteControl.VS/DebuggerHelper/ProfilesObserver.cs
@@ -20,6 +20,7 @@
using System.Reflection;
using System.Management.Instrumentation;
using Microsoft.VisualStudio.RpcContracts.Build;
+using EnvDTE80;
namespace Uno.UI.RemoteControl.VS.DebuggerHelper;
#pragma warning disable VSTHRD010 // Invoke single-threaded types on Main thread
@@ -27,16 +28,25 @@ namespace Uno.UI.RemoteControl.VS.DebuggerHelper;
internal class ProfilesObserver : IDisposable
{
private readonly AsyncPackage _asyncPackage;
+ private readonly Action _debugLog;
private readonly DTE _dte;
private readonly Func _onDebugFrameworkChanged;
private readonly Func _onDebugProfileChanged;
+
+ private record FrameworkServices(object? ActiveDebugFrameworkServices, MethodInfo? SetActiveFrameworkMethod, MethodInfo? GetProjectFrameworksAsyncMethod);
+ private FrameworkServices? _projectFrameworkServices;
+
private string? _currentActiveDebugProfile;
private string? _currentActiveDebugFramework;
private IDisposable? _projectRuleSubscriptionLink;
private UnconfiguredProject? _unconfiguredProject;
- private object? _activeDebugFrameworkServices;
- private MethodInfo? _setActiveFrameworkMethod;
- private MethodInfo? _getProjectFrameworksAsyncMethod;
+
+ // Keep the handlers below in order to avoid collection
+ // and allow DTE to call them.
+ _dispSolutionEvents_ProjectAddedEventHandler? _projectAdded;
+ _dispSolutionEvents_ProjectRemovedEventHandler? _projectRemoved;
+ _dispSolutionEvents_ProjectRenamedEventHandler? _projectRenamed;
+ _dispCommandEvents_AfterExecuteEventHandler? _afterExecute;
public string? CurrentActiveDebugProfile
=> _currentActiveDebugProfile;
@@ -44,53 +54,141 @@ public string? CurrentActiveDebugProfile
public string? CurrentActiveDebugFramework
=> _currentActiveDebugFramework;
- public ProfilesObserver(AsyncPackage asyncPackage, EnvDTE.DTE dte, Func onDebugFrameworkChanged, Func onDebugProfileChanged)
+ public ProfilesObserver(
+ AsyncPackage asyncPackage
+ , EnvDTE.DTE dte
+ , Func onDebugFrameworkChanged
+ , Func onDebugProfileChanged
+ , Action debugLog)
{
_asyncPackage = asyncPackage;
+ _debugLog = debugLog;
_dte = dte;
_onDebugFrameworkChanged = onDebugFrameworkChanged;
_onDebugProfileChanged = onDebugProfileChanged;
+
+ ObserveSolutionEvents();
}
- public async Task ObserveProfilesAsync()
- {
- await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
+ object[]? _existingStartupProjects = [];
- if (_dte.Solution.SolutionBuild.StartupProjects is object[] startupProjects
- && startupProjects.Length > 0)
+ private void TryUpdateSolution()
+ {
+ if (_dte.Solution.SolutionBuild.StartupProjects is object[] newStartupProjects)
{
- var startupProject = (string)startupProjects[0];
+ if (!newStartupProjects.SequenceEqual(_existingStartupProjects))
+ {
+ // log all projects
+ _existingStartupProjects = newStartupProjects;
+ }
- if ((await _dte.GetProjectsAsync()).FirstOrDefault(p => p.UniqueName == startupProject) is Project dteProject
- && (await GetUnconfiguredProjectAsync(dteProject)) is { } unconfiguredProject)
+ if (_unconfiguredProject is null)
{
- _unconfiguredProject = unconfiguredProject;
+ _ = ObserveProfilesAsync();
+ }
+ }
+ }
+
+ public async Task ObserveProfilesAsync()
+ {
+ try
+ {
+ _debugLog("Starting observing profile");
- var configuredProject = unconfiguredProject.Services.ActiveConfiguredProjectProvider?.ActiveConfiguredProject;
- var projectSubscriptionService = configuredProject?.Services.ActiveConfiguredProjectSubscription;
+ await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
- if (projectSubscriptionService is not null)
+ if ((await _dte.GetStartupProjectsAsync()) is { } startupProjects)
+ {
+ if (startupProjects.FirstOrDefault() is Project dteProject
+ && (await GetUnconfiguredProjectAsync(dteProject)) is { } unconfiguredProject)
{
- var projectChangesBlock = DataflowBlockSlim.CreateActionBlock(
- CaptureAndApplyExecutionContext>>(ProjectRuleBlock_ChangedAsync));
+ _debugLog($"Observing {unconfiguredProject.FullPath}");
+
+ _unconfiguredProject = unconfiguredProject;
+ _unconfiguredProject.ProjectUnloading += OnUnconfiguredProject_ProjectUnloadingAsync;
+
+ var configuredProject = unconfiguredProject.Services.ActiveConfiguredProjectProvider?.ActiveConfiguredProject;
+ var projectSubscriptionService = configuredProject?.Services.ActiveConfiguredProjectSubscription;
- var evaluationLinkOptions = new StandardRuleDataflowLinkOptions
+ if (projectSubscriptionService is not null)
{
- RuleNames = ImmutableHashSet.Create("ProjectDebugger"),
- PropagateCompletion = true
- };
-
- var projectBlock = projectSubscriptionService.ProjectRuleSource.SourceBlock.SyncLinkOptions(evaluationLinkOptions, true);
- var unconfiguredProjectBlock = ProjectDataSources.SyncLinkOptions(unconfiguredProject.Capabilities.SourceBlock);
-
- _projectRuleSubscriptionLink = ProjectDataSources.SyncLinkTo(
- projectBlock,
- unconfiguredProjectBlock,
- projectChangesBlock,
- new() { PropagateCompletion = true });
+ var projectChangesBlock = DataflowBlockSlim.CreateActionBlock(
+ CaptureAndApplyExecutionContext>>(ProjectRuleBlock_ChangedAsync));
+
+ var evaluationLinkOptions = new StandardRuleDataflowLinkOptions
+ {
+ RuleNames = ImmutableHashSet.Create("ProjectDebugger"),
+ PropagateCompletion = true
+ };
+
+ var projectBlock = projectSubscriptionService.ProjectRuleSource.SourceBlock.SyncLinkOptions(evaluationLinkOptions, true);
+ var unconfiguredProjectBlock = ProjectDataSources.SyncLinkOptions(unconfiguredProject.Capabilities.SourceBlock);
+
+ _projectRuleSubscriptionLink = ProjectDataSources.SyncLinkTo(
+ projectBlock,
+ unconfiguredProjectBlock,
+ projectChangesBlock,
+ new() { PropagateCompletion = true });
+ }
}
}
}
+ catch (Exception ex)
+ {
+ _debugLog($"Failed to observe {ex}");
+ }
+ }
+
+ private void ObserveSolutionEvents()
+ {
+ _projectAdded = (s) =>
+ {
+ _debugLog($"_projectAdded: {s}");
+ TryUpdateSolution();
+ };
+ _projectRemoved = (s) =>
+ {
+ _debugLog($"_projectRemoved: {s}");
+ TryUpdateSolution();
+ };
+ _projectRenamed = (s, v) =>
+ {
+ _debugLog($"_projectRenamed: {s}");
+ TryUpdateSolution();
+ };
+ _afterExecute = (s, c, o, m) =>
+ {
+ _debugLog($"_afterExecute: {s} {c} {o} {m}");
+ TryUpdateSolution();
+ };
+
+ _debugLog("Observing solution");
+ _dte.Events.SolutionEvents.ProjectAdded += _projectAdded;
+ _dte.Events.SolutionEvents.ProjectRemoved += _projectRemoved;
+ _dte.Events.SolutionEvents.ProjectRenamed += _projectRenamed;
+ _dte.Events.CommandEvents.AfterExecute += _afterExecute;
+ }
+
+ private async Task OnUnconfiguredProject_ProjectUnloadingAsync(object? sender, EventArgs args)
+ {
+ await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
+
+ _debugLog($"unconfiguredProject was unloaded");
+
+ _currentActiveDebugFramework = null;
+ _currentActiveDebugProfile = null;
+
+ // Force a refresh of reflection calls
+ _projectFrameworkServices = null;
+
+ _projectRuleSubscriptionLink?.Dispose();
+ _projectRuleSubscriptionLink = null;
+
+ if (_unconfiguredProject is not null)
+ {
+ _unconfiguredProject.ProjectUnloading -= OnUnconfiguredProject_ProjectUnloadingAsync;
+ _unconfiguredProject = null;
+ }
}
private static Func CaptureAndApplyExecutionContext(Func function)
@@ -115,34 +213,43 @@ private static Func CaptureAndApplyExecutionContext(Func> projectSnapshot)
{
- if (projectSnapshot.Value.Item1.CurrentState.TryGetValue("ProjectDebugger", out var ruleSnapshot))
+ try
{
- ruleSnapshot.Properties.TryGetValue("ActiveDebugProfile", out var activeDebugProfile);
- ruleSnapshot.Properties.TryGetValue("ActiveDebugFramework", out var activeDebugFramework);
-
- if (!string.IsNullOrEmpty(activeDebugProfile) && activeDebugProfile != _currentActiveDebugProfile)
+ if (projectSnapshot.Value.Item1.CurrentState.TryGetValue("ProjectDebugger", out var ruleSnapshot))
{
- var previousProfile = _currentActiveDebugProfile;
- _currentActiveDebugProfile = activeDebugProfile;
+ ruleSnapshot.Properties.TryGetValue("ActiveDebugProfile", out var activeDebugProfile);
+ ruleSnapshot.Properties.TryGetValue("ActiveDebugFramework", out var activeDebugFramework);
- await _onDebugProfileChanged(previousProfile, _currentActiveDebugProfile);
- }
+ if (!string.IsNullOrEmpty(activeDebugProfile) && activeDebugProfile != _currentActiveDebugProfile)
+ {
+ var previousProfile = _currentActiveDebugProfile;
+ _currentActiveDebugProfile = activeDebugProfile;
- if (!string.IsNullOrEmpty(activeDebugFramework) && activeDebugFramework != _currentActiveDebugFramework)
- {
- var previousDebugFramework = _currentActiveDebugProfile;
- _currentActiveDebugFramework = activeDebugFramework;
+ await _onDebugProfileChanged(previousProfile, _currentActiveDebugProfile);
+ }
+
+ if (!string.IsNullOrEmpty(activeDebugFramework) && activeDebugFramework != _currentActiveDebugFramework)
+ {
+ var previousDebugFramework = _currentActiveDebugFramework;
+ _currentActiveDebugFramework = activeDebugFramework;
- await _onDebugFrameworkChanged(previousDebugFramework, _currentActiveDebugFramework);
+ await _onDebugFrameworkChanged(previousDebugFramework, _currentActiveDebugFramework);
+ }
}
}
+ catch (Exception e)
+ {
+ _debugLog($"Failed to process changedAsync: {e}");
+ }
}
public async Task SetActiveTargetFrameworkAsync(string targetFramework)
{
+ _debugLog($"SetActiveTargetFrameworkAsync({targetFramework})");
+
EnsureActiveDebugFrameworkServices();
- if (_setActiveFrameworkMethod?.Invoke(_activeDebugFrameworkServices, [targetFramework]) is Task t)
+ if (_projectFrameworkServices?.SetActiveFrameworkMethod?.Invoke(_projectFrameworkServices.ActiveDebugFrameworkServices, [targetFramework]) is Task t)
{
await t;
}
@@ -150,9 +257,11 @@ public async Task SetActiveTargetFrameworkAsync(string targetFramework)
public async Task?> GetActiveTargetFrameworksAsync()
{
+ _debugLog($"GetActiveTargetFrameworksAsync()");
+
EnsureActiveDebugFrameworkServices();
- if (_getProjectFrameworksAsyncMethod?.Invoke(_activeDebugFrameworkServices, []) is Task?> listTask)
+ if (_projectFrameworkServices?.GetProjectFrameworksAsyncMethod?.Invoke(_projectFrameworkServices.ActiveDebugFrameworkServices, []) is Task?> listTask)
{
return await listTask;
}
@@ -210,27 +319,25 @@ public async Task> GetLaunchProfilesAsync()
private void EnsureActiveDebugFrameworkServices()
{
- if (_setActiveFrameworkMethod is null)
- {
- var provider = _unconfiguredProject?.Services.ActiveConfiguredProjectProvider?.ActiveConfiguredProject?.Services.ExportProvider;
+ var provider = _unconfiguredProject?.Services.ActiveConfiguredProjectProvider?.ActiveConfiguredProject?.Services.ExportProvider;
+ if (_projectFrameworkServices is null && provider is not null)
+ {
var type = Type.GetType("Microsoft.VisualStudio.ProjectSystem.Debug.IActiveDebugFrameworkServices, Microsoft.VisualStudio.ProjectSystem.Managed");
+
if (typeof(MefExtensions).GetMethods().FirstOrDefault(m => m.Name == "GetService") is { } getServiceMethod)
{
var typedMethod = getServiceMethod.MakeGenericMethod(type);
- _activeDebugFrameworkServices = typedMethod.Invoke(null, [provider, /*allow default*/false]);
+ var activeDebugFrameworkServices = typedMethod.Invoke(null, [provider, /*allow default*/false]);
// https://github.com/dotnet/project-system/blob/34eb57b35962367b71c2a1d79f6c486945586e24/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Debug/IActiveDebugFrameworkServices.cs#L20-L21
- if (_activeDebugFrameworkServices.GetType().GetMethod("SetActiveDebuggingFrameworkPropertyAsync") is { } setActiveFrameworkMethod)
- {
- _setActiveFrameworkMethod = setActiveFrameworkMethod;
- }
+ if (activeDebugFrameworkServices.GetType().GetMethod("SetActiveDebuggingFrameworkPropertyAsync") is { } setActiveFrameworkMethod
- // https://github.com/dotnet/project-system/blob/34eb57b35962367b71c2a1d79f6c486945586e24/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Debug/IActiveDebugFrameworkServices.cs#L20-L21
- if (_activeDebugFrameworkServices.GetType().GetMethod("GetProjectFrameworksAsync") is { } getProjectFrameworksAsyncMethod)
+ // https://github.com/dotnet/project-system/blob/34eb57b35962367b71c2a1d79f6c486945586e24/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Debug/IActiveDebugFrameworkServices.cs#L20-L21
+ && activeDebugFrameworkServices.GetType().GetMethod("GetProjectFrameworksAsync") is { } getProjectFrameworksAsyncMethod)
{
- _getProjectFrameworksAsyncMethod = getProjectFrameworksAsyncMethod;
+ _projectFrameworkServices = new(activeDebugFrameworkServices, setActiveFrameworkMethod, getProjectFrameworksAsyncMethod);
}
}
}
diff --git a/src/Uno.UI.RemoteControl.VS/EntryPoint.cs b/src/Uno.UI.RemoteControl.VS/EntryPoint.cs
index d598fd975f82..7fb54d035226 100644
--- a/src/Uno.UI.RemoteControl.VS/EntryPoint.cs
+++ b/src/Uno.UI.RemoteControl.VS/EntryPoint.cs
@@ -3,6 +3,7 @@
using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Pipes;
@@ -19,10 +20,13 @@
using EnvDTE80;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;
+using Microsoft.VisualStudio;
+using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.ProjectSystem;
using Microsoft.VisualStudio.ProjectSystem.Build;
using Microsoft.VisualStudio.ProjectSystem.Debug;
using Microsoft.VisualStudio.ProjectSystem.Properties;
+using Microsoft.VisualStudio.ProjectSystem.VS;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using StreamJsonRpc;
@@ -93,7 +97,7 @@ public EntryPoint(DTE2 dte2, string toolsPath, AsyncPackage asyncPackage, Action
// This will can possibly be removed when all projects are migrated to the sdk project system.
_ = UpdateProjectsAsync();
- _debuggerObserver = new ProfilesObserver(asyncPackage, _dte, OnDebugFrameworkChangedAsync, OnDebugProfileChangedAsync);
+ _debuggerObserver = new ProfilesObserver(asyncPackage, _dte, OnDebugFrameworkChangedAsync, OnDebugProfileChangedAsync, _debugAction);
_ = _debuggerObserver.ObserveProfilesAsync();
}
@@ -111,6 +115,12 @@ private Task> OnProvideGlobalPropertiesAsync()
});
}
+ [MemberNotNull(
+ nameof(_debugAction)
+ , nameof(_infoAction)
+ , nameof(_verboseAction)
+ , nameof(_warningAction)
+ , nameof(_errorAction))]
private void SetupOutputWindow()
{
var ow = _dte2.ToolWindows.OutputWindow;
@@ -406,8 +416,9 @@ private bool IsApplication(Microsoft.Build.Evaluation.Project project)
private async Task OnDebugFrameworkChangedAsync(string? previousFramework, string newFramework)
{
- // In this case, a new TargetFramework was selected. We need to file a matching launch profile, if any.
+ await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
+ // In this case, a new TargetFramework was selected. We need to file a matching launch profile, if any.
if (GetTargetFrameworkIdentifier(newFramework) is { } targetFrameworkIdentifier)
{
_debugAction?.Invoke($"OnDebugFrameworkChangedAsync({previousFramework}, {newFramework}, {targetFrameworkIdentifier})");
@@ -446,6 +457,51 @@ bool IsCompatible(ILaunchProfile profile)
await _debuggerObserver.SetActiveLaunchProfileAsync(msixProfile.Name);
}
}
+
+ await TryReloadWebAssemblyTargetAsync(previousFramework, targetFrameworkIdentifier);
+ }
+ }
+
+ private async Task TryReloadWebAssemblyTargetAsync(string? previousFramework, string targetFrameworkIdentifier)
+ {
+ try
+ {
+ if (previousFramework is not null
+ && GetTargetFrameworkIdentifier(previousFramework) is { } previousTargetFrameworkIdentifier
+ && (
+ previousTargetFrameworkIdentifier == WasmTargetFrameworkIdentifier
+ || targetFrameworkIdentifier == WasmTargetFrameworkIdentifier)
+ && await _dte.GetStartupProjectsAsync() is { Length: > 0 } startupProjects
+ )
+ {
+ _warningAction?.Invoke($"Detected that the active framework was changed from/to WebAssembly, reloading the project (See https://aka.platform.uno/singleproject-vs-wasm-reload)");
+
+ // In this context, in order to work around the fact that VS does not handle Wasm
+ // to be in the same project as other target framework, we're using the `_SelectedTargetFramework`
+ // to reorder the list and make browser-wasm first or not.
+
+ // Assuming serviceProvider is an IServiceProvider instance available in your context
+ if (await _asyncPackage.GetServiceAsync(typeof(SVsSolution)) is IVsSolution solution
+ && solution is IVsSolution4 solution4)
+ {
+ if (solution.GetProjectOfUniqueName(startupProjects[0].UniqueName, out var startupProject) == 0)
+ {
+ if (startupProject.GetGuidProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID.VSHPROPID_ProjectIDGuid, out var guidObj) == 0
+ && guidObj is Guid projectGuid)
+ {
+ // Unload project
+ solution4.UnloadProject(ref projectGuid, (uint)_VSProjectUnloadStatus.UNLOADSTATUS_UnloadedByUser);
+
+ // Reload project
+ solution4.ReloadProject(ref projectGuid);
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ _errorAction?.Invoke($"Failed to reload project {e}");
}
}
@@ -463,7 +519,7 @@ private async Task OnDebugProfileChangedAsync(string? previousProfile, string ne
if (profile.LaunchBrowser
&& FindTargetFramework(WasmTargetFrameworkIdentifier) is { } targetFramework)
{
- _debugAction?.Invoke($"Setting framework {targetFramework}");
+ _errorAction?.Invoke($"Setting framework {targetFramework}");
await _debuggerObserver.SetActiveTargetFrameworkAsync(targetFramework);
}
@@ -471,7 +527,7 @@ private async Task OnDebugProfileChangedAsync(string? previousProfile, string ne
&& compatibleTargetObject is string compatibleTarget
&& FindTargetFramework(compatibleTarget) is { } compatibleTargetFramework)
{
- _debugAction?.Invoke($"Setting framework {compatibleTarget}");
+ _errorAction?.Invoke($"Setting framework {compatibleTarget}");
await _debuggerObserver.SetActiveTargetFrameworkAsync(compatibleTargetFramework);
}
diff --git a/src/Uno.UI.RemoteControl.VS/Helpers/DTEHelper.cs b/src/Uno.UI.RemoteControl.VS/Helpers/DTEHelper.cs
index b2f9b0e96f4b..75f53ca73321 100644
--- a/src/Uno.UI.RemoteControl.VS/Helpers/DTEHelper.cs
+++ b/src/Uno.UI.RemoteControl.VS/Helpers/DTEHelper.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using EnvDTE;
@@ -92,4 +93,25 @@ private static IEnumerable EnumSubProjects(Project folder)
}
}
+ public static async Task GetStartupProjectsAsync(this DTE dte)
+ {
+ await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
+
+ if (dte.Solution.SolutionBuild.StartupProjects is object[] startupProjects
+ && startupProjects.Length > 0)
+ {
+ var projects = await dte.GetProjectsAsync();
+
+ return startupProjects
+ .OfType()
+ .Select(p => projects.FirstOrDefault(p2 =>
+ {
+ Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread();
+ return p2.UniqueName == p;
+ }))
+ .Where(p => p is not null).ToArray();
+ }
+
+ return null;
+ }
}
diff --git a/src/Uno.UI.RemoteControl.VS/Uno.UI.RemoteControl.VS.csproj b/src/Uno.UI.RemoteControl.VS/Uno.UI.RemoteControl.VS.csproj
index d5f43c684020..aa7a63f8933c 100644
--- a/src/Uno.UI.RemoteControl.VS/Uno.UI.RemoteControl.VS.csproj
+++ b/src/Uno.UI.RemoteControl.VS/Uno.UI.RemoteControl.VS.csproj
@@ -30,6 +30,10 @@
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+