85

データグリッドを使用した WPF アプリケーションがあります。Visual Studio 2012 と Blend+SketchFlow プレビューをインストールするまで、アプリケーションは正常に動作していました。今、グリッドからクリップボードにCtrl+を使用してデータをコピーしようとするとC(任意のアプリケーションで)、次の例外が発生します。

System.Runtime.InteropServices.COMException (0x800401D0): OpenClipboard Failed (Exception from HRESULT: 0x800401D0 (CLIPBRD_E_CANT_OPEN))
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode, IntPtr errorInfo)
   at System.Windows.Clipboard.Flush()
   at System.Windows.Clipboard.CriticalSetDataObject(Object data, Boolean copy)
   at System.Windows.Controls.DataGrid.OnExecutedCopy(ExecutedRoutedEventArgs args)
   at System.Windows.Controls.DataGrid.OnExecutedCopy(Object target, ExecutedRoutedEventArgs args)
   at System.Windows.Input.CommandBinding.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
   at System.Windows.Input.CommandManager.ExecuteCommandBinding(Object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
   at System.Windows.Input.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
   at System.Windows.Input.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
   at System.Windows.Input.CommandManager.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
   at System.Windows.UIElement.OnExecutedThunk(Object sender, ExecutedRoutedEventArgs e)
   at System.Windows.Input.ExecutedRoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object target)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.RoutedCommand.ExecuteImpl(Object parameter, IInputElement target, Boolean userInitiated)
   at System.Windows.Input.RoutedCommand.ExecuteCore(Object parameter, IInputElement target, Boolean userInitiated)
   at System.Windows.Input.CommandManager.TranslateInput(IInputElement targetElement, InputEventArgs inputEventArgs)
   at System.Windows.UIElement.OnKeyDownThunk(Object sender, KeyEventArgs e)
   at System.Windows.Input.KeyEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndKeyboardInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawKeyboardActions actions, Int32 scanCode, Boolean isExtendedKey, Boolean isSystemKey, Int32 virtualKey)
   at System.Windows.Interop.HwndKeyboardInputProvider.ProcessKeyAction(MSG& msg, Boolean& handled)
   at System.Windows.Interop.HwndSource.CriticalTranslateAccelerator(MSG& msg, ModifierKeys modifiers)
   at System.Windows.Interop.HwndSource.OnPreprocessMessage(Object param)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
   at System.Windows.Interop.HwndSource.OnPreprocessMessageThunk(MSG& msg, Boolean& handled)
   at System.Windows.Interop.HwndSource.WeakEventPreprocessMessage.OnPreprocessMessage(MSG& msg, Boolean& handled)
   at System.Windows.Interop.ComponentDispatcherThread.RaiseThreadMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()

これは本当に迷惑です。

この問題については、ここや Web 上のさまざまな場所で参照されていますが、実際の解決策はありません。

メッセージをコピーして貼り付けることができなかった (ファイルに書き込む必要があった) ため、Visual Studio でこの例外が発生したときにクリップボードがロックされていることを確認できます。また、コピー プロセスが開始される前に、クリップボードがロックされていませんでした。

この問題を解決するには?

4

11 に答える 11

109

.NET 4.0 を使用しています。同じ問題がありましたが、システムからログオフした後、コードはしばらくの間正常に動作していました。

最後に、代替手段を見つけました。

文字列をクリップボードにコピーしたい場合は、

string data = "Copy This"

今まで私は次の方法を使用していました

Clipboard.SetText(data);

失敗を繰り返していました。次に、 Clipboard クラスのクリップボードにテキストを設定するために使用できる他の方法を調べ、次のことを試しました。

Clipboard.SetDataObject(data);

そしてそれはうまくいきました:)。私は再び問題を抱えたことはありません。

于 2013-07-16T13:57:18.887 に答える
81

これは、WPF クリップボード ハンドラーのバグです。Application.DispatcherUnhandledException イベントで未処理の例外を処理する必要があります。

この属性をApplicationApp.xaml の要素に追加します

DispatcherUnhandledException="Application_DispatcherUnhandledException"

このコードを App.xaml.cs ファイルに追加します

void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
    var comException = e.Exception as System.Runtime.InteropServices.COMException;

    if (comException != null && comException.ErrorCode == -2147221040)
         e.Handled = true;
}
于 2012-11-23T04:39:58.927 に答える
8

私も、ユーザーが ListBox を熟読しているときに情報をクリップボードにコピーするアプリケーションで問題を抱えていました。コピーされた情報は、選択した項目に関連しており、利便性のために他のアプリケーションに貼り付けることができます (前述の情報)。時折、一部のユーザーのシステムで CLIPBRD_E_CANT_OPEN が発生しますが、他のシステムでは発生しません。

まだ競合を修正できていませんが、競合の原因となっているアプリケーションを見つけるためのコードを作成することができました。少なくともこのコードを共有して、誰かに役立つことを願っています。作成したusingステートメント、属性、およびメソッドを追加して、犯人のProcessオブジェクトを見つけます。Processアイテムから、プロセスの名前、PID、メイン ウィンドウのタイトル (ある場合)、およびその他の有用なデータを取得できます。これは、それを呼び出すコードなしで追加したコード行です。(注:コード スニペットの下に、もう 1 つ共有する情報があります):

using System.Diagnostics;               // For Process class
using System.Runtime.InteropServices;   // For DllImport's

...

[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetOpenClipboardWindow();

[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

...

    ///-----------------------------------------------------------------------------
    /// <summary>
    /// Gets the Process that's holding the clipboard
    /// </summary>
    /// <returns>A Process object holding the clipboard, or null</returns>
    ///-----------------------------------------------------------------------------
    public Process ProcessHoldingClipboard()
    {
        Process theProc = null;

        IntPtr hwnd = GetOpenClipboardWindow();

        if (hwnd != IntPtr.Zero)
        {
            uint processId;
            uint threadId = GetWindowThreadProcessId(hwnd, out processId);

            Process[] procs = Process.GetProcesses();
            foreach (Process proc in procs)
            {
                IntPtr handle = proc.MainWindowHandle;

                if (handle == hwnd)
                {
                    theProc = proc;
                }
                else if (processId == proc.Id)
                {
                    theProc = proc;
                }
            }
        }

        return theProc;
    }

その他の注意: コードを少し簡略化するために私が変更したもう 1 つのことは、System.Windows.ClipboardSystem.Windows.Forms.Clipboardに変換することでした ( System.Windows.Forms.Clipboard クラスを参照)。パラメータSetDataObject()メソッドには、再試行回数とミリ秒単位の再試行遅延が含まれます。これにより、少なくとも再試行ノイズの一部がコードから取り除かれました。

あなたの走行距離は異なる場合があります...さらに、これにはまだ出くわしていない副作用がある可能性があるため、誰かがそれらについて知っている場合はコメントしてください. いずれにせよ、これが誰かに役立つことを願っています。

于 2014-01-23T14:40:37.930 に答える
7

TeraCopy(Windows 7、64ビット)をインストールして以来、WPF 4.0および4.5でもこの問題が発生しました。すべての Clipboard.SetText() が System.Runtime.InteropServices.COMException で失敗しました。

私の最初の解決策は TeraCopy をアンインストールすることでした。うまくいきましたが、私はこのアプリケーションが大好きなので、その問題を解決する別の解決策を探す必要がありました。解決策は交換することでした

Clipboard.SetText("my string");

Clipboard.SetDataObject("my string");
于 2014-11-12T01:22:49.530 に答える
2

RichTextBox でも同じ問題がありました。次のコードはランダムにクラッシュしました:

TextRange tr = new TextRange(rich.Document.ContentStart, rich.Document.ContentEnd);
System.Windows.Clipboard.SetDataObject(tr.Text);

System.Windows.Controls.RichTextBox.Copyを使用することをお勧めします

于 2014-07-05T06:31:39.560 に答える