Skip to content

Commit

Permalink
Alternative fix for COMException MILERR_WIN32ERROR and correctly use …
Browse files Browse the repository at this point in the history
…refresh interval when the app starts up.
  • Loading branch information
leonzhou-smokeball committed Jan 10, 2025
1 parent 3d6444c commit 3ec36bf
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 15 deletions.
32 changes: 18 additions & 14 deletions App/Extensions/NotifyIconExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,23 @@ internal static void SetIcon(this NotifyIcon notifyIcon, FrameworkElement textBl
// Render the element with the correct DPI scale.
var dpiScale = VisualTreeHelper.GetDpi(textBlock);

// There's a chance that some native exceptions may be thrown when rendering and setting the icon's image.
// Catch any exception here and retry a few times then fail silently.
DelegateExtensions.RetryOnException<Exception>(() =>
{
var renderTargetBitmap = new RenderTargetBitmap(
(int)Math.Round(DefaultNotifyIconSize * dpiScale.DpiScaleX, MidpointRounding.AwayFromZero),
(int)Math.Round(DefaultNotifyIconSize * dpiScale.DpiScaleY, MidpointRounding.AwayFromZero),
dpiScale.PixelsPerInchX,
dpiScale.PixelsPerInchY,
PixelFormats.Default);
renderTargetBitmap.Render(textBlock);
notifyIcon.Icon = renderTargetBitmap;
App.SetTrayIconUpdateError(null);
}, App.SetTrayIconUpdateError);
// There's a known issue that keep creating RenderTargetBitmap in a WPF app, the COMException: MILERR_WIN32ERROR
// may happen.
// This is reported as https://github.com/dotnet/wpf/issues/3067.
// Manually forcing a GC seems to help.
var renderTargetBitmap =
new RenderTargetBitmap(
(int)Math.Round(DefaultNotifyIconSize * dpiScale.DpiScaleX, MidpointRounding.AwayFromZero),
(int)Math.Round(DefaultNotifyIconSize * dpiScale.DpiScaleY, MidpointRounding.AwayFromZero),
dpiScale.PixelsPerInchX,
dpiScale.PixelsPerInchY,
PixelFormats.Default);
renderTargetBitmap.Render(textBlock);

// Force GC after each RenderTargetBitmap creation to avoid running into COMException: MILERR_WIN32ERROR.
GC.Collect();
GC.WaitForPendingFinalizers();

notifyIcon.Icon = renderTargetBitmap;
}
}
2 changes: 1 addition & 1 deletion App/NotifyIconWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public NotifyIconWindow()
InitializeComponent();

// Setup timer to update the tray icon.
_refreshTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
_refreshTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(Default.RefreshSeconds) };
_refreshTimer.Tick += (_, _) => _batteryStatusUpdateSubject.OnNext(false);
}

Expand Down

0 comments on commit 3ec36bf

Please sign in to comment.