CLIPBRD_E_CANT_OPEN error when setting the Clipboard from .NET

前端 未结 7 1171
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-29 08:08

Why does the following code sometimes causes an Exception with the contents \"CLIPBRD_E_CANT_OPEN\":

Clipboard.SetText(str);

This usually o

相关标签:
7条回答
  • 2020-11-29 08:23

    Use the WinForms version (yes, there is no harm using WinForms in WPF applications), it handles everything you need:

    System.Windows.Forms.SetDataObject(yourText, true, 10, 100);
    

    This will attempt to copy yourText to the clipboard, it remains after your app exists, will attempt up to 10 times, and will wait 100ms between each attempt.

    Ref. https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.clipboard.setdataobject?view=netframework-4.7.2#System_Windows_Forms_Clipboard_SetDataObject_System_Object_System_Boolean_System_Int32_System_Int32_

    0 讨论(0)
  • 2020-11-29 08:25

    This is caused by a bug/feature in Terminal Services clipboard (and possible other things) and the .NET implementation of the clipboard. A delay in opening the clipboard causes the error, which usually passes within a few milliseconds.

    The solution is to try multiple times within a loop and sleep in between.

    for (int i = 0; i < 10; i++)
    {
        try
        {
            Clipboard.SetText(str);
            return;
        }
        catch { }
        System.Threading.Thread.Sleep(10);
    } 
    
    0 讨论(0)
  • 2020-11-29 08:28

    Actually there could be another issue at hand. The framework call (both the WPF and winform flavors) to something like this (code is from reflector):

    private static void SetDataInternal(string format, object data)
    {
        bool flag;
        if (IsDataFormatAutoConvert(format))
        {
            flag = true;
        }
        else
        {
            flag = false;
        }
        IDataObject obj2 = new DataObject();
        obj2.SetData(format, data, flag);
        SetDataObject(obj2, true);
    }
    

    Note that SetDataObject is always called with true in this case.

    Internally that triggers two calls to the win32 api, one to set the data and one to flush it from your app so it's available after the app closes.

    I've seen several apps (some chrome plugin, and a download manager) that listen to the clipboard event. As soon as the first call hits, the app will open the clipboard to look into the data, and the second call to flush will fail.

    Haven't found a good solution except to write my own clipboard class that uses direct win32 API or to call setDataObject directly with false for keeping data after the app closes.

    0 讨论(0)
  • 2020-11-29 08:28

    This happen to me in my WPF application. I got OpenClipboard Failed (Exception from HRESULT: 0x800401D0 (CLIPBRD_E_CANT_OPEN)).

    i use

    ApplicationCommands.Copy.Execute(null, myDataGrid);
    

    solution is to clear the clipboard first

    Clipboard.Clear();
    ApplicationCommands.Copy.Execute(null, myDataGrid);
    
    0 讨论(0)
  • 2020-11-29 08:36

    Actually, I think this is the fault of the Win32 API.

    To set data in the clipboard, you have to open it first. Only one process can have the clipboard open at a time. So, when you check, if another process has the clipboard open for any reason, your attempt to open it will fail.

    It just so happens that Terminal Services keeps track of the clipboard, and on older versions of Windows (pre-Vista), you have to open the clipboard to see what's inside... which ends up blocking you. The only solution is to wait until Terminal Services closes the clipboard and try again.

    It's important to realize that this is not specific to Terminal Services, though: it can happen with anything. Working with the clipboard in Win32 is a giant race condition. But, since by design you're only supposed to muck around with the clipboard in response to user input, this usually doesn't present a problem.

    0 讨论(0)
  • 2020-11-29 08:42

    I know this question is old, but the problem still exists. As mentioned before, this exception occurs when the system clipboard is blocked by another process. Unfortunately, the are many snipping tools, programs for screenshots and file copy tools which can block the Windows clipboard. So you will get the exception every time you try to use Clipboard.SetText(str) when such a tool is installed on your PC.

    Solution:

    never use

    Clipboard.SetText(str);
    

    use instead

    Clipboard.SetDataObject(str);
    
    0 讨论(0)
提交回复
热议问题