Skip to content

Comments

Add automatic update system using GitHub Releases#37

Draft
arthur-moebios wants to merge 3 commits intoAntonyCorbett:masterfrom
arthur-moebios:master
Draft

Add automatic update system using GitHub Releases#37
arthur-moebios wants to merge 3 commits intoAntonyCorbett:masterfrom
arthur-moebios:master

Conversation

@arthur-moebios
Copy link

This pull request introduces a complete automatic update mechanism for JwlMediaWin. The application now checks for the latest release published on GitHub and, if a newer version is available, offers to download and install it automatically.

Key Features

Added VersionDetection class to fetch and parse version data from GitHub’s releases/latest API.

Implemented UpdateService that:

Compares the local assembly version with the remote version.

Prompts the user to install updates.

Downloads the installer (.exe or .msi) and runs it (with elevation when needed).

Logs detailed update information using Serilog.

Integrated automatic background check at app startup.

Added optional tray menu item “Check for updates…” to trigger the update manually.

Implemented robust fallback behavior:

Opens the GitHub Releases page if direct download fails.

Handles user-canceled UAC prompts and missing assets gracefully.

Creates an installer log file for debugging update failures.

Technical Notes

Compatible with C# 7.3 / .NET Framework 4.8.

Uses only standard APIs (no external dependencies).

Logs use English messages consistent with the project style.

Maintains silent installer support (/VERYSILENT /NORESTART), with logging to %TEMP%/JwlMediaWinSetup.log.

New Files

Services/UpdateService.cs

Services/IUpdateService.cs

VersionDetection.cs

Modified Files

App.xaml.cs: runs update check in background on startup.

This pull request introduces a complete automatic update mechanism for JwlMediaWin.
The application now checks for the latest release published on GitHub and, if a newer version is available, offers to download and install it automatically.

Key Features

Added VersionDetection class to fetch and parse version data from GitHub’s releases/latest API.

Implemented UpdateService that:

Compares the local assembly version with the remote version.

Prompts the user to install updates.

Downloads the installer (.exe or .msi) and runs it (with elevation when needed).

Logs detailed update information using Serilog.

Integrated automatic background check at app startup.

Added optional tray menu item “Check for updates…” to trigger the update manually.

Implemented robust fallback behavior:

Opens the GitHub Releases page if direct download fails.

Handles user-canceled UAC prompts and missing assets gracefully.

Creates an installer log file for debugging update failures.

Technical Notes

Compatible with C# 7.3 / .NET Framework 4.8.

Uses only standard APIs (no external dependencies).

Logs use English messages consistent with the project style.

Maintains silent installer support (/VERYSILENT /NORESTART), with logging to %TEMP%/JwlMediaWinSetup.log.

New Files

Services/UpdateService.cs

Services/IUpdateService.cs

VersionDetection.cs

Modified Files

App.xaml.cs: runs update check in background on startup.
@AntonyCorbett
Copy link
Owner

@arthur-moebios Thank you for your PR - I'll review it asap.

Copy link
Owner

@AntonyCorbett AntonyCorbett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a large number of style warnings associated with changes and additions in the PR. If you can adjust that would be great, but I can do it after merging if needed. Thanks again for your hard work.

using GalaSoft.MvvmLight.Messaging;
using Hardcodet.Wpf.TaskbarNotification;
using PubSubMessages;
using JwlMediaWin.Services;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just using Services

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, thanks

}
catch
{
// optional: log here if you have a static logger ready at this time
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the logger is configured, so perhaps we can log the error, please.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, i´ve add System.Exception to catch the ex, ok?

// Se quiser ainda mais verboso: remova /NORESTART para ver prompts de reboot, se houver.
}

Process proc = Process.Start(psi);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we starting the process twice? See also line 142

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, my fault

if (info.AssetUri == null)
{
Log.Warning("[Update] No downloadable asset found. Opening Releases page instead.");
Process.Start(info.HtmlPage.AbsoluteUri);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use ProcessStartInfo { UseShellExecute = true } to reliably open URLs on .NET Framework.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, thanks for information

@arthur-moebios
Copy link
Author

There are a large number of style warnings associated with changes and additions in the PR. If you can adjust that would be great, but I can do it after merging if needed. Thanks again for your hard work.

Sure brother! I’ll do and commit asap

thank you!

@arthur-moebios
Copy link
Author

Summary

  • Fix double-launch of installer.
  • Improve GitHub API compatibility and parsing resilience.

✅ Changes

  • Networking & GitHub API

  • Add short request timeout for update checks: HttpClient.Timeout = TimeSpan.FromSeconds(10).

  • Pin API version: X-GitHub-Api-Version: 2022-11-28 (prevents future default changes).

  • Keep required headers:

  • User-Agent: JwlMediaWin-Updater

  • Accept: application/vnd.github+json

  • Safer JSON parsing of assets:
    var assets = jo["assets"] as JArray ?? new JArray();
    (prevents InvalidCastException when assets is missing or not an array).

  • SemVer normalization

  • Extend normalization to strip pre-release (-beta, -rc.1) and build metadata (+build.5) before System.Version parsing:

  • Cuts at the first - or + (whichever comes first).

  • Pads to 4 components for System.Version (1.2 → 1.2.0.0, 1.2.3 → 1.2.3.0).

  • Installer launch & shutdown flow

  • Remove duplicate Process.Start(psi); now a single authoritative start with elevation.

  • Handle elevation failures robustly:

  • Win32Exception.NativeErrorCode == 740: retry without elevation (msiexec /passive or /VERYSILENT for EXE).

  • NativeErrorCode == 1223: user canceled UAC → do not shut down the app.

  • Otherwise: open Releases page as fallback.

  • Delay ~1.2s to let UAC/installer surface, then shutdown only once (via Application.Current.Dispatcher when available).

  • File download

  • Use GetAsync(..., HttpCompletionOption.ResponseHeadersRead, ct) + EnsureSuccessStatusCode().

  • Copy stream with CopyToAsync(fs, 81920, ct).

  • UI thread safety

  • MessageBox.Show(...) routed via Application.Current.Dispatcher.Invoke(...) when available to ensure UI thread.

  • Open URL reliably on .NET Framework

  • Replace raw Process.Start(url) with:

var psi = new ProcessStartInfo { FileName = url, UseShellExecute = true, Verb = "open" };
Process.Start(psi);

Fallback: cmd /c start "" "" if the primary attempt fails.

Logging

  • More explicit/consistent messages for each branch:
  • Download path, PID, MSI vs EXE, log path.
  • Timeouts (TaskCanceledException) logged as info, not error.
  • Clear messages on fallback paths and user-canceled UAC.

Files touched

UpdateService.cs
VersionDetection.cs

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please would you describe the use of FrameMotionDetector?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely, it's a file shouldn't be there. I was developing a detector to call zoom sharing for personal use. But didn't notice was on commit.

FrameMotionDetector is a low-level screen capture and frame-difference analyzer.
It’s used by JwlMediaWin to determine when JW Library changes its visual content — specifically, to detect whether the current media context is an image or a video window.

Because JW Library doesn’t expose an API or event for “media started” or “media stopped”, the app needs a way to observe screen changes directly.
That’s what FrameMotionDetector provides.

⚙️ How it works
1. Captures the JW Library client area

GetClientRect(hWnd, out RECT rect);
GetDC(hWnd); BitBlt(...);

It uses Win32 APIs (user32.dll + gdi32.dll) to copy the current window pixels into a Bitmap.

2.	Compares consecutive frames
•	Each captured frame is converted into grayscale or byte array.
•	It calculates the difference between the current and the previous frame.
•	If the amount of pixel change exceeds a threshold, it flags “motion detected”.
3.	Publishes motion events
•	The caller (e.g. Fixer or MediaWatcher) uses this to decide:
•	No motion → likely a still image (slide or paused video).
•	Motion present → likely a playing video.
4.	Resource management
•	Uses P/Invoke to manage device contexts (GetDC, ReleaseDC).
•	Implements IDisposable to ensure cleanup of bitmaps and HDCs.
•	Runs on a background thread with short sleeps between frames (e.g., 100–200 ms).

🧩 Integration in JwlMediaWin
• Fixer or MediaAndCoreWindows creates a FrameMotionDetector instance targeting JW Library’s media window handle (HWND).
• The detector continuously samples frames to identify whether the user started a video.
• Once motion is detected, the app automatically:
• Triggers the Zoom sharing workflow (if automation is enabled).
• Switches internal context from Image → Video.

Example:

using (var detector = new FrameMotionDetector(jwMediaHwnd))
{
detector.Start();

while (true)
{
    if (detector.IsMotionDetected)
        UpdateContext(MediaContext.Video);
    else
        UpdateContext(MediaContext.Image);

    Thread.Sleep(200);
}

}

Design advantages
• Non-intrusive: doesn’t hook into JW Library’s internals.
• Universal: works regardless of app version or platform changes.
• Lightweight: captures a small region and uses bitmap diffs, not full video processing.

I'll wait for instructions of what do about it, commit again removing the file and references?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation - interesting stuff :) Let's keep it simple here and remove from the PR please.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, removing! :)

<Reference Include="System.Drawing.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Drawing.Common.10.0.0-rc.1.25451.107\lib\net462\System.Drawing.Common.dll</HintPath>
</Reference>
<Reference Include="System.Drawing.Design" />
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove the hints and hence the ref to rc?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sure

}
finally
{
Log.Logger.Information("==== Exit ====");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This log message is misleading. It logs the thread's completion, but "Exit" is what is logged when the app closes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok!

</Reference>
<Reference Include="System.Drawing.Design">
<HintPath>..\..\..\..\..\..\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Drawing.Design.dll</HintPath>
</Reference>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we only need System.Drawing

Updates based on comments
@arthur-moebios
Copy link
Author

Commited changes, thanks for attention brother

@AntonyCorbett AntonyCorbett marked this pull request as draft October 30, 2025 19:36
@AntonyCorbett
Copy link
Owner

Commited changes, thanks for attention brother

Thanks. I've converted the PR to a draft as it doesn't build at the moment. Let me know if you have any questions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants