剪贴板已被 Idle.exe 使用

本文关键字:exe 使用 Idle 剪贴板 | 更新日期: 2023-09-27 17:57:14

我一直在开发一个使用鼠标和键盘模拟的程序,并且经常需要抓取/设置剪贴板数据。

我遇到了这个问题,显然很多人都遇到了这个问题,剪贴板正被另一个进程使用,所以"剪贴板.SetDataObject"抛出异常"请求的剪贴板操作不成功"。

       private void CheckSetClipboard(string s)
    {
        IntPtr ClipWindow = GetOpenClipboardWindow();
        if (ClipWindow != null && ClipWindow != (IntPtr)0)
        {
            uint wid;
            GetWindowThreadProcessId(ClipWindow, out wid);
            Process p = Process.GetProcessById((int)wid);
            Console.WriteLine("Process using Clipboard: " + p.ProcessName);
        } else {
            Console.WriteLine("ClipWindow:" + ClipWindow.ToString());
        }
            OpenClipboard(IntPtr.Zero);
            EmptyClipboard();
            CloseClipboard();
        try { Clipboard.SetDataObject(s, true, 10, 50); }
        catch{// Clipboard.SetDataObject(s, true, 10, 50);
        }
    }

我尝试了一些解决方案,如上面的代码所示,但最终错误再次弹出。这次我决定全力以赴,并使用剪贴板获取进程的进程名称。
这是控制台显示的内容:

使用剪贴板的进程:空闲

空闲.exe如何使用剪贴板?
我甚至可以杀死该进程以释放剪贴板吗?
我做错了什么吗?

最后,我只是希望能够毫无故障地进行剪贴板操作。Ctrl+c 和 Ctrl+v 永远不会失败,为什么我的 c# 代码会失败?

更多信息:
我传递到剪贴板的数据是"-0.09261441"或类似的数字。
错误始终发生在 catch{...} 部分。

[已解决]多亏了汉斯,我才能够弄清楚。我误解了 pinvoke 上的提示和示例代码。那个try{}catch{}中的这两个剪贴板操作显然在某种程度上是冲突的。正确的方法是使用 try{}catch{try{}catch{},我没有使用也没有测试。

当我注释掉第二个剪贴板操作时,我的问题似乎已经解决了。

剪贴板已被 Idle.exe 使用

我用你的代码创建了一个一次性类(有一些变化),并填充了缺少的方法并运行没有问题和挂起。我在通知应用程序中进行测试。

我从按钮调用该方法并从一个文本框复制,然后将值粘贴到另一个文本框中,粘贴的结果有效而不会挂起。请注意我是如何通过使类从 IDisposable 继承来自动处置句柄的。

试试这个代码

 class ClipboardUtility : IDisposable
{
    private bool disposed = false;
    //If the function succeeds, the return value is the handle to the window that has the clipboard open. 
    //If no window has the clipboard open, the return value is NULL. 
    //To get extended error information, call GetLastError. 
    [DllImport("user32.dll")]
    static extern IntPtr GetOpenClipboardWindow();
    [DllImport("user32.dll", SetLastError = true)]
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
    [DllImport("user32.dll", SetLastError = true)]
    static extern bool OpenClipboard(IntPtr hWndNewOwner);
    [DllImport("user32.dll", SetLastError = true)]
    static extern bool CloseClipboard();
    [DllImport("user32.dll")]
    static extern bool EmptyClipboard();
    private IntPtr ClipWindow;
    public void CheckSetClipboard(string s)
    {
        //IntPtr ClipWindow = GetOpenClipboardWindow();
          ClipWindow = GetOpenClipboardWindow();
        Console.WriteLine("handle IntPtr= {0}", ClipWindow);
        //  if (ClipWindow != null && ClipWindow != (IntPtr)0)
        if (ClipWindow != null )
        {
            Console.WriteLine("ClipWindow_" + ClipWindow.ToString());
            uint wid = GetWindowThreadProcessId(ClipWindow, out wid);
            Process p = Process.GetProcessById((int)wid);
            Console.WriteLine("Process using Clipboard: " + p.ProcessName);
        }
        else
        {
            Console.WriteLine("error: {0}", Marshal.GetLastWin32Error());
          //  Console.WriteLine("0 is not idle");
        }
        //Marshal.FreeHGlobal(ClipWindow);
        //OpenClipboard(IntPtr.Zero);
        //EmptyClipboard();
        //CloseClipboard();
        //Console.WriteLine("s: " + s);
        try
        {
            Clipboard.SetDataObject(s, true, 10, 50);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
           // Clipboard.SetDataObject(s, true, 10, 50);
        }
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            CloseHandle(ClipWindow);
            ClipWindow = IntPtr.Zero;
            disposed = true;
        }
    }
    [DllImport("Kernal32")]
    private extern static Boolean CloseHandle(IntPtr handle);
}