54 votes

Comment gérer un presse-papiers bloqué et d'autres bizarreries ?

Au cours des deux dernières heures, j'ai recherché un bogue assez spécifique qui se produit lorsqu'une autre application a le presse-papiers ouvert. Essentiellement, comme le presse-papiers est une ressource partagée (conformément à la norme "Pourquoi mon presse-papiers partagé ne fonctionne pas ?" ) et vous tentez d'exécuter

Clipboard.SetText(string)

ou

Clipboard.Clear().

L'exception suivante est levée :

System.Runtime.InteropServices.ExternalException: Requested Clipboard operation did not succeed. 
    at System.Windows.Forms.Clipboard.ThrowIfFailed(Int32 hr)
    at System.Windows.Forms.Clipboard.SetDataObject(Object data, Boolean copy, Int32 retryTimes, Int32 retryDelay)
    at System.Windows.Forms.Clipboard.SetText(String text, TextDataFormat format)
    at System.Windows.Forms.Clipboard.SetText(String text)

Ma solution initiale consistait à réessayer après une courte pause, jusqu'à ce que je réalise que Clipboard.SetDataObject possède des champs pour le nombre de tentatives et la durée du délai. Le comportement par défaut de .NET est d'essayer 10 fois avec un délai de 100 msec.

Il y a une dernière chose qui a été notée par l'utilisateur final. En effet, malgré la levée de l'exception, l'opération de copie dans le presse-papiers fonctionne toujours. Je n'ai pas été en mesure de trouver d'autres informations sur la raison de cette situation.

Ma solution actuelle consiste à ignorer l'exception en silence... Est-ce vraiment la meilleure solution ?

45voto

jitbit Points 8072

Une autre solution serait d'utiliser Clipboard.SetDataObject au lieu de Clipboard.SetText .

Selon cet article de MSDN cette méthode a deux paramètres - délais de réessai y retryDelay - que vous pouvez utiliser comme ceci :

System.Windows.Forms.Clipboard.SetDataObject(
    "some text", // Text to store in clipboard
    false,       // Do not keep after our application exits
    5,           // Retry 5 times
    200);        // 200 ms delay between retries

0 votes

Le problème auquel je suis confronté est que même avec des valeurs élevées pour retryTimes et retryDelay (20/500), le fait d'avoir Firefox ouvert provoque toujours l'échec. C'est donc étrange...

4 votes

S'il vous plaît pas il y a deux Clipboard dans le cadre de .NET. L'une d'entre elles se trouve dans le System.Windows.Forms et un autre dans l'espace de noms System.Windows (pour WPF). Seul le premier a une surcharge avec le nombre de tentatives et le délai.

28voto

Phil Price Points 1441

Comme le presse-papiers est partagé par toutes les applications de l'interface utilisateur, vous rencontrerez ce problème de temps en temps. Évidemment, vous ne voulez pas que votre application se plante si elle ne parvient pas à écrire dans le presse-papiers, donc il est raisonnable de traiter gracieusement les exceptions externes. Je suggère de présenter une erreur à l'utilisateur si l'appel SetObjectData pour écrire dans le presse-papiers échoue.

Une suggestion serait d'utiliser (via P/Invocation ) user32!GetOpenClipboardWindow pour voir si une autre application a le presse-papiers ouvert. Il renverra le HWND de la fenêtre qui a le presse-papiers ouvert, ou IntPtr.Zero si aucune application ne l'avait ouvert. Vous pouvez tourner sur la valeur jusqu'à ce qu'elle IntPtr.Zero pour une durée déterminée.

0 votes

Je me suis renseigné sur GetOpenClipboardWindow ; il semble que ce soit la meilleure solution aux problèmes d'accès au presse-papiers. Merci pour votre réponse.

0 votes

Comment obtenir le processus qui bloque le presse-papiers - voir : stackoverflow.com/questions/6583642/

1 votes

Fermez juste le presse-papiers d'abord. Voir ma réponse.

13voto

Jeff Roe Points 1175

J'ai rencontré cette erreur aujourd'hui. J'ai décidé de la traiter en informant l'utilisateur de l'application qui s'est potentiellement mal comportée. Pour ce faire, vous pouvez faire quelque chose comme ceci :

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

[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern int GetWindowText(int hwnd, StringBuilder text, int count);

private void btnCopy_Click(object sender, EventArgs e)
{
    try
    {
        Clipboard.Clear();
        Clipboard.SetText(textBox1.Text);
    }
    catch (Exception ex)
    {
        string msg = ex.Message;
        msg += Environment.NewLine;
        msg += Environment.NewLine;
        msg += "The problem:";
        msg += Environment.NewLine;
        msg += getOpenClipboardWindowText();
        MessageBox.Show(msg);
    }
}

private string getOpenClipboardWindowText()
{
    IntPtr hwnd = GetOpenClipboardWindow();
    StringBuilder sb = new StringBuilder(501);
    GetWindowText(hwnd.ToInt32(), sb, 500);
    return sb.ToString();
    // example:
    // skype_plugin_core_proxy_window: 02490E80
}

Pour moi, le titre de la fenêtre problématique était "skype_plugin_core_proxy_window". J'ai cherché des informations à ce sujet et j'ai été surpris de ne trouver qu'une seule réponse, en russe de surcroît. J'ajoute donc cette réponse, à la fois pour donner un autre résultat pour cette chaîne de caractères, et pour fournir une aide supplémentaire pour mettre en lumière des applications potentiellement malhonnêtes.

0 votes

Il a été mentionné dans d'autres sujets similaires qu'il existe des versions de Skype qui se comportent assez mal lorsqu'il s'agit du presse-papiers (partagé).

4voto

Tony Bennett Points 11

Faire un Clipboard.Clear() avant Clipboard.SetDataObject(pasteString, true) semble faire l'affaire.

La suggestion antérieure de fixer retryTimes y retryDelay n'a pas fonctionné pour moi et dans tous les cas les valeurs par défaut sont retryTimes = 10 y retryDelay = 100ms

0voto

C'est un peu merdique... Mais ça a résolu mon problème.

Réessayer le clear() après un délai.

Vous trouverez plus d'informations dans l'article de blog Comment gérer un presse-papiers bloqué - erreur Clipboard.Clear() .

0 votes

Révéler peut-être qu'il s'agit de votre billet de blog.

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