82 votes

OpenClipboard a échoué lors de la copie de données collées à partir de wpf DataGrid

J'ai une application WPF, à l'aide de grille de données. L'application a bien fonctionné jusqu'à ce que j'ai installé VS2012 et de Mélange+SketchFlow aperçu. Maintenant, quand j'essaie de copier les données de la grille dans le presse-papiers ctrl+C (dans n'importe quelle application), je reçois exception suivante:

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()

C'est vraiment ennuyeux.

J'ai vu quelques références à ce problème ici et sur divers endroits sur le web, avec pas de solution réelle.

Je peux vérifier que le presse-papiers est verrouillé lorsque cette exception est soulevée dans visual studio, que je ne pouvais pas copier coller le message (dû l'écrire dans un fichier). Aussi, le presse-papiers n'était pas verrouillée avant le processus de copie commencé.

A quelqu'un ici ont ce problème et résolu?

106voto

kushdilip Points 705

Nous utilisons .NET 4.0. Nous avons eu le même problème, mais après déconnexion du système, le code utilisé pour bien fonctionner pendant un certain temps. Enfin trouvé une alternative.

Si vous souhaitez copier une chaîne de caractères dans le presse-papiers

string data = "Copy This"

Jusqu'à maintenant j'ai été en utilisant la méthode suivante

Clipboard.SetText(data);

Il n'était pas, encore et encore. Puis j'ai regardé d'autres méthodes pour mettre du texte dans le presse-papiers au http://msdn.microsoft.com/en-IN/library/system.windows.clipboard.aspx et essayé de suivre

Clipboard.SetDataObject(data);

et CELA a fonctionné :). Jamais eu de problème à nouveau.

81voto

alexw Points 2328

C'est un bogue dans le gestionnaire de presse-papiers WPF. Vous devez gérer l'exception non gérée dans l'événement Application.DispatcherUnhandledException.

Ajoutez cet attribut à l'élément Application dans votre App.xaml

 DispatcherUnhandledException="Application_DispatcherUnhandledException"
 

Ajoutez ce code à votre fichier 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;
}
 

7voto

John Points 52

Moi aussi, j'ai eu un problème dans une application où j'ai copier les informations dans le presse-papiers en tant qu'utilisateurs de parcourir une zone de liste. L'information qui est copié est liée à l'élément sélectionné, et il leur permet de le coller (dit-info) dans d'autres applications, pour des raisons de commodité. Parfois je reçois le CLIPBRD_E_CANT_OPEN sur certains systèmes de l'utilisateur, mais pas sur d'autres.

Alors que je n'ai toujours pas été en mesure de résoudre le conflit, j'ai été en mesure de créer un peu de code pour trouver l'application à l'origine de la discorde. J'aimerais au moins partager ce code en espérant que cela aide quelqu'un. Je vais ajouter l' aide de déclaration, les attributs, et la méthode que j'ai créée pour trouver le Procédé objet de la coupable. À partir du Processus d' élément, vous pouvez obtenir le processus de " nom, PID, le principal titre de la fenêtre (si elle en a un), et potentiellement d'autres données utiles. Voici les lignes de code que j'ai ajouté, sans le code qui l'appelle. (REMARQUE: ci-Dessous l'extrait de code que j'ai encore une friandise à partager):

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;
    }

AUTRE REMARQUE: Une autre chose que j'ai changé qui a simplifié mon code un peu était de convertir de l'utilisation du Système.De Windows.Presse-papiers de Système.De Windows.Les formulaires.Presse-papiers (voir Système.De Windows.Les formulaires.Classe Clipboard)parce que ce dernier dispose d'un 4-paramètre SetDataObject() méthode qui comprend un nombre de tentatives et une nouvelle tentative de retard en millisecondes. Au moins enlevé une partie de la nouvelle tentative de bruit à partir de mon code.

Votre kilométrage peut varier...en plus il peut y avoir des effets secondaires dans la ce qui je ne l'ai pas encore tombé sur, donc si quelqu'un sait d'eux, s'il vous plaît commentaire. En tout cas, j'espère que cela s'avère utile à quelqu'un.

2voto

AVEbrahimi Points 2190

J'ai le même problème avec RichTextBox, le code suivant s'est écrasé de manière aléatoire:

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

Il semble préférable d'utiliser System.Windows.Controls.RichTextBox.Copy

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X