From c036a8dcb8c8a821807fa72c7198220ec78b5e52 Mon Sep 17 00:00:00 2001 From: kennethcheng Date: Sun, 6 Sep 2026 23:04:18 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A4=8D=E5=88=B6=E6=8C=89=E9=92=AE?= =?UTF-8?q?=E5=8A=A0=E9=87=8D=E8=AF=95=E9=80=BB=E8=BE=91(CLIPBRD=5FE=5FCAN?= =?UTF-8?q?T=5FOPEN=20=E6=98=AF=E5=B8=B8=E8=A7=81=20race)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 bug:点 [复制] 按钮偶发 "OpenClipboard 失败 0x800401D0 (CLIPBRD_E_CANT_OPEN)"。 根因:Clipboard.SetText 不自带重试,剪贴板被其他进程占着(RDP 同步、杀软扫描、用户刚复制过其他内容)时会抛 COMException 0x800401D0,典型 race condition。 修法:CopyMessageButton_Click 里包一层重试循环,最多 10 次,每次失败后 Thread.Sleep 50ms 再试(总等待上限 ~500ms,对 UI 不可感知)。失败兜底弹 MessageBox 显示重试次数 + HRESULT 0x 代码,方便用户诊断。 只捕获 COMException(剪贴板错误都走 OLE COM 接口),其他异常类型继续向上抛。 --- MainWindow.xaml.cs | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index ac931ce..4782b9c 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -292,11 +292,31 @@ public partial class MainWindow : Window { if (HistoryList.SelectedItem is not GotifyMessage msg) return; var text = BuildFullMessageText(msg); - try + + // 剪贴板常被其他进程占着(RDP、杀软、其他复制操作),CLIPBRD_E_CANT_OPEN 是常见 race。 + // Clipboard.SetText 不自带重试,自己包一层:最多 10 次,每次等 50ms。 + const int MaxAttempts = 10; + const int DelayMs = 50; + Exception? lastEx = null; + bool ok = false; + for (int attempt = 1; attempt <= MaxAttempts; attempt++) + { + try + { + Clipboard.SetText(text); + ok = true; + break; + } + catch (System.Runtime.InteropServices.COMException ex) + { + lastEx = ex; + System.Threading.Thread.Sleep(DelayMs); + } + } + + if (ok) { - Clipboard.SetText(text); _logger?.Info($"Copied message to clipboard. id={msg.Id}"); - // 按钮反馈:短暂显示「已复制 ✓」 if (sender is Button btn) { var origContent = btn.Content; @@ -313,11 +333,12 @@ public partial class MainWindow : Window timer.Start(); } } - catch (Exception ex) + else { - _logger?.Error("Copy to clipboard failed.", ex); - MessageBox.Show($"复制失败:{ex.Message}", "Windows Gotify", - MessageBoxButton.OK, MessageBoxImage.Warning); + _logger?.Error("Copy to clipboard failed after retries.", lastEx); + MessageBox.Show( + $"复制失败:剪贴板被其他程序占用,重试 {MaxAttempts} 次仍未成功。\n请关闭正在使用剪贴板的程序后重试。\n\n错误:0x{(lastEx?.HResult ?? 0):X8}", + "Windows Gotify", MessageBoxButton.OK, MessageBoxImage.Warning); } }