Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clipboard.SetDataObject randomly fails with CLIPBRD_E_CANT_OPEN #3166

Closed
RussKie opened this issue Apr 30, 2020 · 8 comments
Closed

Clipboard.SetDataObject randomly fails with CLIPBRD_E_CANT_OPEN #3166

RussKie opened this issue Apr 30, 2020 · 8 comments
Labels
area-Clipboard Issues related to Clipboard

Comments

@RussKie
Copy link
Member

RussKie commented Apr 30, 2020

Problem description:

The tests that exercise Clipboard randomly fail on my computer with CLIPBRD_E_CANT_OPEN (0x800401D0) in either of these two points:

HRESULT hr;
int retry = retryTimes;
do
{
if (data is IComDataObject ido)
{
hr = Ole32.OleSetClipboard(ido);
}
else
{
hr = Ole32.OleSetClipboard(dataObject);
}
if (hr != HRESULT.S_OK)
{
if (retry == 0)
{
throw new ExternalException(SR.ClipboardOperationFailed, (int)hr);
}
retry--;
Thread.Sleep(millisecondsTimeout: retryDelay);
}
}
while (hr != 0);
if (copy)
{
retry = retryTimes;
do
{
hr = Ole32.OleFlushClipboard();
if (hr != HRESULT.S_OK)
{
if (retry == 0)
{
throw new ExternalException(SR.ClipboardOperationFailed, (int)hr);
}
retry--;
Thread.Sleep(millisecondsTimeout: retryDelay);
}
}
while (hr != 0);
}

I struggle to make any logical conclusions about a cause. There seemed to be other reports from people suffering from similar issues (e.g. ColinDabritz/PoeItemAnalyzer#1, https://stackoverflow.com/q/68666/2338036)

Expected behavior:

The code is resilient.

@RussKie
Copy link
Member Author

RussKie commented Apr 30, 2020

I've written a test harness (borrowed from https://stackoverflow.com/a/21311270/2338036), but I was unable to catch anything with it:

        public void Clipboard_SetDataObject_InvokeObjectBoolIntIntNotIComDataObject_GetReturnsExpected(object data, bool copy, int retryTimes, int retryDelay)
        {
            try
            {
                Clipboard.SetDataObject(data, copy, retryTimes, retryDelay);

                Assert.Equal(data, Clipboard.GetDataObject().GetData(data.GetType()));
                Assert.True(Clipboard.ContainsData(data.GetType().FullName));
            }
            catch (System.Runtime.InteropServices.ExternalException ex)
            {
                Process p = ProcessHoldingClipboard();
                if (p != null)
                {
                    throw new Exception($"Clipboard blocked with '{ex.ErrorCode}' reason, process pid:{p.Id} {p.ProcessName}");
                }
                else
                {
                    throw;
                }
            }
        }

        [DllImport("User32.dll", ExactSpelling = true, SetLastError = true)]
        private static extern IntPtr GetOpenClipboardWindow();

        private Process ProcessHoldingClipboard()
        {
            Process theProc = null;

            IntPtr hwnd = GetOpenClipboardWindow();

            if (hwnd != IntPtr.Zero)
            {
                uint processId;
                uint threadId = Interop.User32.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;
        }

@RussKie
Copy link
Member Author

RussKie commented Apr 30, 2020

@JeremyKuhne @weltkante any thoughts?

@weltkante
Copy link
Contributor

The linked stackoverflow article makes sense. Personally I never have seen this behavior, I suspect it depends on 3rd party software running on your machine, perhaps its badly behaving by keeping the clipboard open for too long instead of immediately performing its operation and closing it.

The tests that exercise Clipboard randomly fail on my computer

What is the rate of failure? If its regular enough you could close 3rd party software and try to figure out whos fault it might be.

Its probably gonna be hard to figure out via debugging since this is cross process, it probably would need a kernel debugger to capture the whole OLE/clipboard state in a dump to examine, something beyond my level of expertise.

I don't have any other idea than trying to identify which application is handling the clipboard badly. Except maybe you could fine tune the loop to make it even more resilient, but if another application is behaving badly and keeping the clipboard open over several seconds this won't help.

@RussKie
Copy link
Member Author

RussKie commented Apr 30, 2020

What is the rate of failure? If its regular enough you could close 3rd party software and try to figure out whos fault it might be.

It is failing quite consistently. The challenge is to figure out what that software is :) I don't run any clipboard managers... Other than 1Password I run a pretty vanilla dev build - VS, Office, Teams

@danmoseley
Copy link
Member

Would it help to leave Spy++ running? Is been a long time since I used it.
https://docs.microsoft.com/en-us/visualstudio/debugger/spy-increment-help?view=vs-2019

@JeremyKuhne

@JeremyKuhne
Copy link
Member

I'd add the check directly to the code under an assert to try and track it down. Note that you shouldn't have to walk for the matching process, Process has Process.GetProcessById().

@JeremyKuhne JeremyKuhne added this to the 5.0 milestone May 14, 2020
@JeremyKuhne
Copy link
Member

@Tanya-Solyanik suggests that there is a timeout between repeated calls, which would be worth investigating.

@RussKie
Copy link
Member Author

RussKie commented May 27, 2020

I'm no longer observing the issue. I think this was addressed in #3276.

@RussKie RussKie closed this as completed May 27, 2020
@RussKie RussKie removed this from the 5.0 milestone May 27, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Feb 1, 2022
@RussKie RussKie added the area-Clipboard Issues related to Clipboard label May 5, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Clipboard Issues related to Clipboard
Projects
None yet
Development

No branches or pull requests

4 participants