Skip to content
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
f1a0efa
feat: Introduce `ApplicationLaunchMonitor` for correlating app launch…
carldebilly Sep 12, 2025
481c22c
fix(remote-control): use TimeProvider timers and stabilize launch tim…
carldebilly Sep 12, 2025
76abdaf
refactor(remote-control): Simplify `ServerProcessor` attribute usage …
carldebilly Oct 2, 2025
7e00f51
chore: Improve uni test assembly discovery helpers
carldebilly Oct 2, 2025
d967317
feat(app-launch): Add support for tracking application launches and r…
carldebilly Oct 3, 2025
4aff59c
refactor(hot-reload): Remove unused field from `FileUpdateProcessor` …
carldebilly Oct 3, 2025
63cf93e
docs: Update contribution and telemetry guidelines
carldebilly Oct 3, 2025
80c9c36
refactor: Improved telemetry testing. No functional changes
carldebilly Oct 3, 2025
12b87aa
feat(dev-server): Add `AssemblyInfoReader` and improve app launch con…
carldebilly Oct 3, 2025
5b8ed56
ci: Fix build
carldebilly Oct 4, 2025
290ff58
ci: Another try to fix build (net9 vs net10)
carldebilly Oct 4, 2025
b6905e6
feat(app-launch): Add scavenging for stale launches and enhance conne…
carldebilly Oct 6, 2025
30cc2fc
ci: Trying to fix tests on CI
carldebilly Oct 6, 2025
3fd4550
fix(logging): Ensure consistent naming for binlog files and remove re…
carldebilly Oct 6, 2025
4d1995f
chore: Temporary add output for failing test - will be removed
carldebilly Oct 6, 2025
37ce641
ci: Trying to fix the build again
carldebilly Oct 6, 2025
c0e15d3
feat(app-launch): Introduce `VsAppLaunchStateService` for determinist…
carldebilly Oct 9, 2025
f8e491f
refactor(tests): Convert test namespace and class declarations to fil…
carldebilly Oct 9, 2025
d429acf
feat(app-launch): Add `VsAppLaunchIdeBridge` to integrate Play/Build …
carldebilly Oct 10, 2025
17fb9ae
feat(app-launch): Preserve original instance during state transitions…
carldebilly Oct 10, 2025
38d094f
feat(app-launch): Add retention handling for unmatched launches and t…
carldebilly Oct 10, 2025
cc11a72
fix(app-launch): Dispose of `_scavengeTimer` to prevent resource leak…
carldebilly Oct 10, 2025
b9b3008
feat(app-launch): Add new endpoint to register app launches via assem…
carldebilly Oct 10, 2025
a9ef47d
fix(app-launch): Ensure interception only occurs for debug builds in …
carldebilly Oct 10, 2025
a239cd2
fix(app-launch): Update endpoint to use encoded paths and align with …
carldebilly Oct 10, 2025
5219c6a
feat(app-launch): Refactor app launch endpoints and improve platform …
carldebilly Oct 14, 2025
a3e7149
feat(app-launch): Add IDE and plugin metadata support across launch r…
carldebilly Oct 15, 2025
90f0a5d
feat(app-launch): Added new integration test to validate timeout beha…
carldebilly Oct 15, 2025
4eca719
feat(app-launch): Add UnoNotifyAppLaunch MSBuild target for IDE integ…
carldebilly Oct 17, 2025
60e4e53
fix(app-launch): Enforce Debug configuration for UnoNotifyAppLaunch t…
carldebilly Oct 17, 2025
3d89e97
fix(app-launch): Update telemetry event properties for clarity and co…
carldebilly Oct 17, 2025
1db41d4
feat(telemetry): Enhance telemetry documentation with source links an…
carldebilly Oct 17, 2025
7be8c13
fix(logs): Suppress WebSocket closure noise in logs
carldebilly Oct 17, 2025
8c5b065
feat(app-launch): Improve late-match classification for app launches
carldebilly Oct 22, 2025
e87d18d
chore(build): Update target frameworks and project references for com…
carldebilly Oct 22, 2025
1c10409
docs(telemetry): Adjust documentation about telemetry events
carldebilly Oct 22, 2025
c514182
fix(tests): Remove unnecessary null-forgiveness operators
carldebilly Oct 22, 2025
e93cef3
chore(remote-control): Correct typos
carldebilly Oct 22, 2025
a7f26a6
feat(app-launch): Include IDE version in app launch state consumer in…
carldebilly Oct 22, 2025
7c4c963
chore(code-style): Apply consistent formatting across tests and helpers
carldebilly Oct 22, 2025
78612c8
chore(tests): Pin MessagePack dependency to version 3.1.4
carldebilly Oct 22, 2025
e4349c2
chore(build): Post-rebase conflict solving.
carldebilly Oct 22, 2025
cc11309
fix(logging): Include assembly file name in error message for failed …
carldebilly Oct 22, 2025
3feb2ad
fix(remote-control): Replace recursive re-scheduling with single peri…
carldebilly Oct 22, 2025
354bba8
fix(remote-control): Signal connection establishment once and handle …
carldebilly Oct 22, 2025
e58847c
fix(app-launch): Make IsDebug optional and default to false instead o…
carldebilly Oct 22, 2025
602a481
chore(app-launch): Apply PR review suggestions
carldebilly Oct 28, 2025
130d34b
feat(remote-control): Introduce configuration helpers for parsing and…
carldebilly Oct 29, 2025
b626a6d
fix(app-launch): Rename MSBuild task properties for consistent Uno-pr…
carldebilly Oct 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
<PackageReference Update="AwesomeAssertions" Version="9.2.0" />
<PackageReference Update="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
<PackageReference Update="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
<PackageReference Update="Microsoft.Extensions.TimeProvider.Testing" Version="9.9.0" />
<PackageReference Update="Uno.Extensions.Logging.WebAssembly.Console" Version="1.7.0" />
<PackageReference Update="Uno.Extensions.Logging.WebAssembly.OSLog" Version="1.4.0" />
<PackageReference Update="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" />
Expand Down
87 changes: 87 additions & 0 deletions src/Uno.Sdk/Tasks/UnoNotifyAppLaunchToDevServer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Uno.Sdk.Tasks;

public sealed class UnoNotifyAppLaunchToDevServer_v0 : Task
{
[Required] public string Port { get; set; } = string.Empty;
[Required] public string TargetPath { get; set; } = string.Empty;
public string IsDebug { get; set; } = string.Empty;
public string Ide { get; set; } = string.Empty;
public string Plugin { get; set; } = string.Empty;

[Output] public bool Success { get; set; }
[Output] public string ResponseContent { get; set; } = string.Empty;

public override bool Execute()
{
// Validate
if (string.IsNullOrWhiteSpace(Port) || !ushort.TryParse(Port, out var portNum) || portNum == 0)
{
Log.LogError("UnoRemoteControlPort must be a valid port number between 1 and 65535.");
return Success = false;
}
if (string.IsNullOrWhiteSpace(TargetPath))
{
Log.LogError("TargetPath is required.");
return Success = false;
}

var encodedPath = WebUtility.UrlEncode(TargetPath);

var parts = new List<string>();
void Add(string name, string value)
{
if (!string.IsNullOrEmpty(value))
parts.Add($"{name}={Uri.EscapeDataString(value)}");
}

Add("ide", Ide);
Add("plugin", Plugin);

// IsDebug is optional: treat empty/null as "false"
var isDebugValue = false;
if (!string.IsNullOrEmpty(IsDebug) && bool.TryParse(IsDebug, out var parsed))
{
isDebugValue = parsed;
}
Add("isDebug", isDebugValue ? "true" : "false");

var qs = parts.Count > 0 ? "?" + string.Join("&", parts) : string.Empty;
var url = $"http://localhost:{portNum}/applaunch/asm/{encodedPath}{qs}";

try
{
using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };
var response = client.GetAsync(url).GetAwaiter().GetResult();

Log.LogMessage(MessageImportance.High,
$"[NotifyDevServer] GET {url} -> {(int)response.StatusCode} {response.ReasonPhrase}");

if (response.IsSuccessStatusCode)
{
ResponseContent = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
Success = true;
return true;
}
else
{
Success = false;
ResponseContent = string.Empty;
return false;
}
}
catch (Exception ex)
{
Log.LogWarning($"[NotifyDevServer] GET {url} failed: {ex.GetType().Name}: {ex.Message}");
Success = false;
ResponseContent = string.Empty;
return false;
}
}
}
72 changes: 72 additions & 0 deletions src/Uno.Sdk/targets/Uno.AppLaunch.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<!--
This file defines the UnoNotifyAppLaunch target used to notify the DevServer (RemoteControl)
when an application has been launched, so that the DevServer can monitor that the launched app
connects back in a timely manner. This is used to detect launch failures and report them to telemetry.

This target is intended to be invoked after the application has been built, but before it is launched, by
the IDE tooling (e.g. Visual Studio Code, Rider, etc). Is it not required for VisualStudio, which is using
a different mechanism to do the same thing. The implementation in this version is in the `AppLaunch` folder
of the `Uno.UI.RemoteControl.VS` project.

IMPORTANT: This target should only be called with Debug configuration (-c:Debug or -p:Configuration=Debug).
It will fail with an error if called with any other configuration (e.g., Release).

Other IDEs will call this target by specifying the `UnoRemoteControlPort` property using the following command:

```shell
dotnet build <app csproj> -c:Debug -t:UnoNotifyAppLaunch -p:TargetFramework=<tfm to launch> -p:NoBuild=true -restore:false -v:d -noLogo -low -p:Ide=<ide info> -p:Plugin=<Uno plugin version> -p:IsDebug=false
```

To retrieve the HTTP response content (MVID and target framework info), use -getProperty:

```shell
dotnet build <app csproj> -c:Debug -t:UnoNotifyAppLaunch -getProperty:UnoNotifyAppLaunchHttpResponse -p:TargetFramework=<tfm> -p:NoBuild=true -restore:false -p:Ide=<ide> -p:Plugin=<version> -p:IsDebug=false
```
-->

<PropertyGroup>
<UnoNotifyAppLaunchDependsOn>$(UnoNotifyAppLaunchDependsOn);GetTargetPath</UnoNotifyAppLaunchDependsOn>
</PropertyGroup>

<UsingTask TaskName="Uno.Sdk.Tasks.UnoNotifyAppLaunchToDevServer_v0"
AssemblyFile="$(MSBuildThisFileDirectory)netstandard2.0\Uno.Sdk_v0.dll" />
<Target Name="UnoNotifyAppLaunch"
DependsOnTargets="$(UnoNotifyAppLaunchDependsOn)"
Condition="'$(TargetFramework)'!=''">

<Message Importance="Low"
Text="NotifyAppLaunch: TFM=$(TargetFramework) TargetPath=$(TargetPath) Configuration=$(Configuration)"/>

<Error Text="UnoNotifyAppLaunch target should only be called with Debug configuration. Current configuration: $(Configuration)"
Condition="'$(Configuration)' != 'Debug'"/>

<Error Text="UnoRemoteControlPort property must be defined to use UnoNotifyAppLaunch target."
Condition="'$(UnoRemoteControlPort)' == ''"/>

<Error Text="Target assembly file not found: $(TargetPath)"
Condition="!Exists('$(TargetPath)')"/>

<!-- Pass the new properties -->
<UnoNotifyAppLaunchToDevServer_v0
Port="$(UnoRemoteControlPort)"
TargetPath="$(TargetPath)"
Ide="$(Ide)"
Plugin="$(Plugin)"
IsDebug="$(IsDebug)">
<Output TaskParameter="Success" PropertyName="_UnoLaunchSuccess"/>
<Output TaskParameter="ResponseContent" PropertyName="UnoNotifyAppLaunchHttpResponse"/>
</UnoNotifyAppLaunchToDevServer_v0>

<Error Text="Failed to notify devserver for assembly: $(TargetPath)" Importance="High" Condition="'$(_UnoLaunchSuccess)' != 'True'"/>

<Message Text="Successfully notified devserver for assembly: $(TargetPath)"
Condition="'$(_UnoLaunchSuccess)' == 'True'"/>

<Message Text="DevServer response: $(UnoNotifyAppLaunchHttpResponse)"
Condition="'$(_UnoLaunchSuccess)' == 'True' AND '$(UnoNotifyAppLaunchHttpResponse)' != ''"/>
</Target>

</Project>
3 changes: 3 additions & 0 deletions src/Uno.Sdk/targets/Uno.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,7 @@

<Import Project="Uno.SingleProject.VS.Build.targets"
Condition=" '$(UnoSingleProject)' == 'true' AND '$(BuildingInsideVisualStudio)' == 'true' " />

<!-- App Launch notification target for IDE integrations -->
<Import Project="Uno.AppLaunch.targets" />
</Project>
26 changes: 14 additions & 12 deletions src/Uno.UI-Skia-only.slnf
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
{
{
"solution": {
"path": "Uno.UI.slnx",
"projects": [
"AddIns\\Uno.UI.Foldable\\Uno.UI.Foldable.netcoremobile.csproj",
"AddIns\\Uno.UI.GooglePlay\\Uno.UI.GooglePlay.netcoremobile.csproj",
"AddIns\\Uno.UI.Lottie\\Uno.UI.Lottie.netcoremobile.csproj",
"AddIns\\Uno.UI.Lottie\\Uno.UI.Lottie.Reference.csproj",
"AddIns\\Uno.UI.Lottie\\Uno.UI.Lottie.Skia.csproj",
"AddIns\\Uno.UI.Lottie\\Uno.UI.Lottie.Tests.csproj",
"AddIns\\Uno.UI.Lottie\\Uno.UI.Lottie.Wasm.csproj",
"AddIns\\Uno.UI.Lottie\\Uno.UI.Lottie.netcoremobile.csproj",
"AddIns\\Uno.UI.MSAL\\Uno.UI.MSAL.Reference.csproj",
"AddIns\\Uno.UI.MSAL\\Uno.UI.MSAL.Skia.csproj",
"AddIns\\Uno.UI.MSAL\\Uno.UI.MSAL.Wasm.csproj",
"AddIns\\Uno.UI.MSAL\\Uno.UI.MSAL.netcoremobile.csproj",
"AddIns\\Uno.UI.Maps\\Uno.UI.Maps.netcoremobile.csproj",
"AddIns\\Uno.UI.MediaPlayer.Skia.Win32\\Uno.UI.MediaPlayer.Skia.Win32.csproj",
"AddIns\\Uno.UI.MediaPlayer.Skia.X11\\Uno.UI.MediaPlayer.Skia.X11.csproj",
"AddIns\\Uno.UI.MediaPlayer.WebAssembly\\Uno.UI.MediaPlayer.WebAssembly.csproj",
"AddIns\\Uno.UI.MSAL\\Uno.UI.MSAL.netcoremobile.csproj",
"AddIns\\Uno.UI.MSAL\\Uno.UI.MSAL.Reference.csproj",
"AddIns\\Uno.UI.MSAL\\Uno.UI.MSAL.Skia.csproj",
"AddIns\\Uno.UI.MSAL\\Uno.UI.MSAL.Wasm.csproj",
"AddIns\\Uno.UI.Svg\\Uno.UI.Svg.netcoremobile.csproj",
"AddIns\\Uno.UI.Svg\\Uno.UI.Svg.Reference.csproj",
"AddIns\\Uno.UI.Svg\\Uno.UI.Svg.Skia.csproj",
"AddIns\\Uno.UI.Svg\\Uno.UI.Svg.netcoremobile.csproj",
"AddIns\\Uno.UI.WebView.Skia.X11\\Uno.UI.WebView.Skia.X11.csproj",
"AddIns\\Uno.WinUI.Graphics2DSK\\Uno.WinUI.Graphics2DSK.Crossruntime.csproj",
"AddIns\\Uno.WinUI.Graphics3DGL\\Uno.WinUI.Graphics3DGL.csproj",
"SamplesApp\\Benchmarks.Shared\\SamplesApp.Benchmarks.shproj",
"SamplesApp\\SamplesApp.Shared\\SamplesApp.Shared.shproj",
"SamplesApp\\SamplesApp.Skia.Generic\\SamplesApp.Skia.Generic.csproj",
"SamplesApp\\SamplesApp.Skia.WebAssembly.Browser\\SamplesApp.Skia.WebAssembly.Browser.csproj",
"SamplesApp\\SamplesApp.Skia.netcoremobile\\SamplesApp.Skia.netcoremobile.csproj",
"SamplesApp\\SamplesApp.Skia.WebAssembly.Browser\\SamplesApp.Skia.WebAssembly.Browser.csproj",
"SamplesApp\\SamplesApp.Skia\\SamplesApp.Skia.csproj",
"SamplesApp\\SamplesApp.UITests.Generator\\Uno.Samples.UITest.Generator.csproj",
"SamplesApp\\SamplesApp.UITests\\SamplesApp.UITests.csproj",
Expand All @@ -46,27 +46,29 @@
"SourceGenerators\\Uno.UI.Tasks\\Uno.UI.Tasks.csproj",
"Uno.Foundation.Logging\\Uno.Foundation.Logging.csproj",
"Uno.Foundation.Runtime.WebAssembly\\Uno.Foundation.Runtime.WebAssembly.csproj",
"Uno.Foundation\\Uno.Foundation.netcoremobile.csproj",
"Uno.Foundation\\Uno.Foundation.Reference.csproj",
"Uno.Foundation\\Uno.Foundation.Skia.csproj",
"Uno.Foundation\\Uno.Foundation.Wasm.csproj",
"Uno.Foundation\\Uno.Foundation.netcoremobile.csproj",
"Uno.Sdk\\Uno.Sdk.csproj",
"Uno.UI.Adapter.Microsoft.Extensions.Logging\\Uno.UI.Adapter.Microsoft.Extensions.Logging.csproj",
"Uno.UI.Composition\\Uno.UI.Composition.Reference.csproj",
"Uno.UI.Composition\\Uno.UI.Composition.Skia.csproj",
"Uno.UI.DevServer.Cli\\Uno.UI.DevServer.Cli.csproj",
"Uno.UI.Dispatching\\Uno.UI.Dispatching.netcoremobile.csproj",
"Uno.UI.Dispatching\\Uno.UI.Dispatching.Reference.csproj",
"Uno.UI.Dispatching\\Uno.UI.Dispatching.Skia.csproj",
"Uno.UI.Dispatching\\Uno.UI.Dispatching.Wasm.csproj",
"Uno.UI.Dispatching\\Uno.UI.Dispatching.netcoremobile.csproj",
"Uno.UI.FluentTheme.v1\\Uno.UI.FluentTheme.v1.Skia.csproj",
"Uno.UI.FluentTheme.v2\\Uno.UI.FluentTheme.v2.Skia.csproj",
"Uno.UI.FluentTheme\\Uno.UI.FluentTheme.Skia.csproj",
"Uno.UI.RemoteControl.Controller\\Uno.UI.RemoteControl.Controller.csproj",
"Uno.UI.RemoteControl.DevServer.Tests\\Uno.UI.RemoteControl.DevServer.Tests.csproj",
"Uno.UI.RemoteControl.Host\\Uno.UI.RemoteControl.Host.csproj",
"Uno.UI.RemoteControl.Messaging\\Uno.UI.RemoteControl.Messaging.csproj",
"Uno.UI.RemoteControl.Server.Processors\\Uno.UI.RemoteControl.Server.Processors.csproj",
"Uno.UI.RemoteControl.Server\\Uno.UI.RemoteControl.Server.csproj",
"Uno.UI.RemoteControl.TestProcessor\\Uno.UI.RemoteControl.TestProcessor.csproj",
"Uno.UI.RemoteControl.VS\\Uno.UI.RemoteControl.VS.csproj",
"Uno.UI.RemoteControl\\Uno.UI.RemoteControl.Skia.csproj",
"Uno.UI.Runtime.Skia.Android\\Uno.UI.Runtime.Skia.Android.csproj",
Expand All @@ -87,10 +89,10 @@
"Uno.UI\\Uno.UI.Reference.csproj",
"Uno.UI\\Uno.UI.Skia.csproj",
"Uno.UWPSyncGenerator\\Uno.UWPSyncGenerator.csproj",
"Uno.UWP\\Uno.netcoremobile.csproj",
"Uno.UWP\\Uno.Reference.csproj",
"Uno.UWP\\Uno.Skia.csproj",
"Uno.UWP\\Uno.Wasm.csproj",
"Uno.UWP\\Uno.netcoremobile.csproj"
"Uno.UWP\\Uno.Wasm.csproj"
]
}
}
6 changes: 3 additions & 3 deletions src/Uno.UI-UnitTests-only.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
"Uno.UI.FluentTheme.v1\\Uno.UI.FluentTheme.v1.Tests.csproj",
"Uno.UI.FluentTheme.v2\\Uno.UI.FluentTheme.v2.Tests.csproj",
"Uno.UI.FluentTheme\\Uno.UI.FluentTheme.Tests.csproj",
"Uno.UI.RemoteControl.DevServer.Tests\\Uno.UI.RemoteControl.DevServer.Tests.csproj",
"Uno.UI.Tests.ViewLibraryProps\\Uno.UI.Tests.ViewLibraryProps.csproj",
"Uno.UI.Tests.ViewLibrary\\Uno.UI.Tests.ViewLibrary.csproj",
"Uno.UI.Tests\\Uno.UI.Unit.Tests.csproj",
"Uno.UI.Toolkit\\Uno.UI.Toolkit.Tests.csproj",
"Uno.UI\\Uno.UI.Tests.csproj",
"Uno.UWP\\Uno.Tests.csproj",
"Uno.UI.RemoteControl.DevServer.Tests\\Uno.UI.RemoteControl.DevServer.Tests.csproj"
"Uno.UWP\\Uno.Tests.csproj"
]
}
}
}
Loading
Loading