L'OpenClipboard a échoué lorsqu'on a copié les données de collage à partir de la base de données WPF.

j'ai une application WPF utilisant datagrid. L'application a bien fonctionné jusqu'à ce que J'installe Visual Studio 2012 et Blend+SketchFlow preview. Maintenant, quand j'essaie de copier les données de la grille dans le bloc-notes avec Ctrl + C (dans n'importe quelle application), j'obtiens l'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 à divers endroits sur le web, sans véritable solution.

je peux vérifier que le presse-papiers est verrouillé lorsque cette exception est soulevée dans Visual Studio, car je ne pouvais pas copier coller le message (a dû l'écrire dans un fichier). De plus, le presse-papiers n'était pas verrouillé avant le début du processus de copie.

Comment résoudre ce problème?

57
demandé sur akjoshi 2012-10-07 17:29:51

9 réponses

nous utilisons .NET 4.0. Nous avions le même problème, mais après avoir déconnecté le système, le code fonctionnait bien pendant un certain temps.

finalement nous avons trouvé l'alternative.

si vous voulez copier une chaîne de caractères dans le presse-papiers,

string data = "Copy This"

Jusqu'à présent j'utilisais la méthode suivante

Clipboard.SetText(data);

il a échoué encore et encore. Puis j'ai regardé d'autres méthodes pour mettre du texte dans le presse-papiers dans Classe Clipboard et j'ai essayé le suivant:

Clipboard.SetDataObject(data);

Et ça a marché :). Je n'ai jamais eu de nouveau le problème.

73
répondu kushdilip 2017-10-15 11:09:44

C'est un bug dans le Gestionnaire de presse-papiers WPF. Vous devez gérer l'exception sans entrave dans la demande.DispatcherUnhandledException event.

ajouter cet attribut à l'élément Application de votre application.xaml

DispatcherUnhandledException="Application_DispatcherUnhandledException"

ajoutez ce code à votre application.XAML.fichier 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;
}
67
répondu Alex Wiese 2013-05-27 22:53:07

moi aussi, j'ai eu un problème dans une application où je copie des informations dans le presse-papiers que les utilisateurs parcourent une boîte de liste. L'information qui est copiée est liée à l'article sélectionné, et il leur permet de la coller (dit info) dans d'autres applications pour la commodité. De temps en temps je reçois le CLIPBRD_E_CANT_OPEN sur les systèmes de certains utilisateurs, mais pas sur d'autres.

alors que je n'ai pas encore été en mesure de fixer l'argument, j'ai été en mesure de créez du code pour trouver l'application à l'origine de la contestation. J'aimerais au moins partager ce code en espérant que cela aide quelqu'un. Je vais ajouter le en utilisant déclaration, attributs, et la méthode que j'ai créé pour trouver le processus objet du coupable. À partir de l'item Process , vous pouvez obtenir le nom du processus, le PID, le titre de la fenêtre principale (s'il y en a un) et d'autres données potentiellement utiles. Voici les lignes de code que j'ai ajouté sans la code qui l'appelle. ( NOTE: ci-dessous l'extrait de code j'ai encore une info à 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 NOTE: une autre chose que j'ai changée qui a simplifié mon code un peu était de passer de l'utilisation du système .Windows.Presse-papiers à système.Windows.Forme.Bloc-notes (voir Système.Windows.Forme.Classe de bloc-notes ) parce que cette dernière a un 4-paramètre SetDataObject () méthode qui comprend un nombre de réessais et un délai de réessais en millisecondes. Cela a au moins enlevé une partie de la reprise noise de mon code.

Votre kilométrage peut varier...de plus, il peut y avoir des effets secondaires dans ce que je n'ai pas encore trébuché sur, Donc si quelqu'un les connaît s'il vous plaît commenter. En tout cas, j'espère que cela s'avère utile à la quelqu'un.

5
répondu John 2014-01-23 14:40:37

j'ai également eu ce problème dans WPF 4.0 et 4.5 depuis que j'ai installé TeraCopy (Windows 7, 64-bit). Tous Les Presse-Papiers.SetText () a échoué avec un système.Runtime.InteropServices.COMException.

ma première solution a été de désinstaller TeraCopy - cela a fonctionné, mais j'adore cette application, donc j'ai dû chercher une autre solution pour résoudre ce problème. La solution était de remplacer

Clipboard.SetText("my string");

avec

Clipboard.SetDataObject("my string");
5
répondu pr0gg3r 2017-10-15 14:20:47

J'ai eu le même problème avec RichTextBox. Le code suivant s'est écrasé au hasard:

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

il semble préférable d'utiliser le système .Windows.Contrôle.RichTextBox.Copie

2
répondu AVEbrahimi 2017-10-15 14:19:26

j'ai eu un problème pour récupérer des données XAML depuis le presse-papiers avec .NET 4.6.1.

message d'erreur:

Openclipboard Failed (Exception from HRESULT: 0x800401D0 (CLIPBRD_E_CANT_OPEN))

je l'ai résolu comme suit:

int counter = 0;
object xamlClipData = null;

while (xamlClipData == null)
{
    try
    {
        if (counter > 10)
        {
            System.Windows.MessageBox.Show("No access to clipboard xaml data.");
            break;
        }

        counter++;

        if (System.Windows.Clipboard.GetDataObject().GetDataPresent(DataFormats.Xaml))
        {
            xamlClipData = System.Windows.Clipboard.GetData(DataFormats.Xaml);
        }
    }
    catch { }
}
2
répondu Pollitzer 2017-10-15 14:25:11

j'ai eu le même problème en copiant des cellules Excel au presse-papiers et en obtenant des données du presse-papiers comme une chaîne HTML.

Vous pouvez utiliser (tout-try-catch) comme dans le code ci-dessous.

Excel.Application exap = new Microsoft.Office.Interop.Excel.Application();
Excel.Workbook wb = exap.Workbooks.Open(
                      sourceFileNameTextBox.Text,
                      Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                      Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                      Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                      Type.Missing, Type.Missing);
Excel.Sheets sh = wb.Worksheets;

bool clip = false;

// Copy Excel cells to clipboard
while (!clip)
{
    try
    {
        ws.Cells.get_Range(cells[0], cells[1]).Copy(Type.Missing);
        clip = true;
    }
    catch
    {
        clip = false;
    }
}

string b = "";

// Get Excel cells data from the clipboard as HTML

clip = false;
while(!clip)
{
    try
    {
        b = Clipboard.GetData(DataFormats.Html) as string;
        clip = true;
    }
    catch
    {
        clip = false;
    }
}

aussi, vous pouvez avoir un compteur dans le while si la boucle est plus de 10 fois ou plus, exception se produisent. Je teste son compteur maximum est un et en boucle de temps de travail de bloc-notes.

1
répondu Majid gharaei 2017-10-15 14:24:05

il y a une signature d'événement/méthode de DataGrid pour ce but précis Copieringrowclipboardcontent(object sender, DataGridRowClipboardEventArgs e) et est plus fiable que le presse-papier.SetDataObject (données) ou Presse-papiers.SetText (data).

Voici comment l'utiliser.

mettre "FullRow" dans le mode SelectionUnit pour dataGrid appelé myDataGrid

<DataGrid x:Name="myDataGrid" SelectionUnit="FullRow"></DataGrid>

nous avons une méthode, myDataGrid_CopyingRowClipboardContent, qui obtient appelé pour chaque ligne dans le dataGrid pour copier son contenu dans le bloc-notes. Par exemple, pour un datagrid avec sept lignes, il est appelé sept fois.

public int clipboardcalledcnt { get; set; } // CopyingRowClipboardContent invoked count
private void myDataGrid_CopyingRowClipboardContent(object sender, DataGridRowClipboardEventArgs e)
{
    PathInfo cellpath = new PathInfo(); // A custom class to hold path information
    string path = string.Empty;

    DataGrid dgdataPaths = (DataGrid)sender;
    int rowcnt = dgdataPaths.SelectedItems.Count;

    cellpath = (PathInfo)e.Item;

    path = "Row #" + clipboardcalledcnt + " Len=" + cellpath.Length.ToString() + ", path=" + cellpath.Path;

    e.ClipboardRowContent.Clear();

    if (clipboardcalledcnt == 0) // Add header to clipboard paste
        e.ClipboardRowContent.Add(new DataGridClipboardCellContent("", null, "--- Clipboard Paste ---\t\t\n")); // \t cell divider, repeat (number of cells - 1)

    clipboardcalledcnt++;
    e.ClipboardRowContent.Add(new DataGridClipboardCellContent(path, null, path));

    if (clipboardcalledcnt == rowcnt)
        clipboardcalledcnt = 0;
}
0
répondu Markus 2017-10-15 14:28:07

ajouter ma réponse à la question so mentionnée à titre de référence -

trouvé par Andrew Smith à http://blogs.infragistics.com/forums/t/35379.aspx -

techniquement, un seul procédé peut ouvrir le presse-papiers donc si un autre le processus a ouvert la les demandes suivantes échouer jusqu'à ce que le les premières versions du presse-papiers. Cela a été en quelque sorte manipulé dans les WinForms Classe de bloc-notes où il serait de nouveau l'ensemble avec un temps de retard entre chaque essai mais la classe de bloc-notes WPF ne fait pas cela ainsi si elle échoue sur la première montre l'exception se produit. Même alors, nous devrions probablement attraper l'exception et augmenter l'erreur d'opération de bloc-notes si elle ne fonctionne toujours pas.

la même chose est expliquée et certains moyens de la corriger sont mentionnés sur ce blog italien -

WPF DataGrid Clipboard BUG (?) Et du travail (mise en Cache de traduction) ( Orignal Lien )

suite au forum MSDN suggère qu'il pourrait s'agir d'un problème propre à la machine -

CLIPBRD_E_CANT_OPEN exception lors de la copie au bloc-notes à partir d'un DataGrid

0
répondu akjoshi 2018-01-29 10:51:42