剪贴板已被 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{},我没有使用也没有测试。
当我注释掉第二个剪贴板操作时,我的问题似乎已经解决了。
我用你的代码创建了一个一次性类(有一些变化),并填充了缺少的方法并运行没有问题和挂起。我在通知应用程序中进行测试。
我从按钮调用该方法并从一个文本框复制,然后将值粘贴到另一个文本框中,粘贴的结果有效而不会挂起。请注意我是如何通过使类从 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);
}