Idle.exe 已在使用剪贴板
Clipboard already in use by Idle.exe
我一直在开发一个使用鼠标和键盘模拟的程序,并且经常需要 grab/set 剪贴板数据。
我已经 运行 解决了这个问题,显然很多人都遇到过,剪贴板正在被另一个进程使用,所以 "Clipboard.SetDataObject" 抛出异常 "Requested Clipboard operation did not succeed."
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);
}
}
我尝试了一些如上面代码所示的解决方案,但最终错误再次弹出。这次我决定全力以赴,并使用剪贴板获取进程的进程名称。
这是控制台显示的内容:
Process using Clipboard: Idle
Idle.exe 如何使用剪贴板?
我什至可以终止该进程以释放剪贴板吗?
我做错了什么吗?
归根结底,我只想能够无故障地进行剪贴板操作。 Ctrl+c 和 Ctrl+v 永远不会失败,为什么我的 C# 代码会失败?
更多信息:
我传递到剪贴板的数据是“-0.09261441”或类似的数字。
错误总是发生在 catch{...} 部分。
[已解决]
多亏了汉斯,我才能够弄明白。
我误解了 pinvoke 上的提示和示例代码。
try{}catch{} 中的这两个剪贴板操作在某种程度上显然是冲突的。正确的方法是使用 try{}catch{try{}catch{}} ,我没有使用也没有测试。
当我注释掉第二个剪贴板操作时,我的问题似乎暂时自行解决了。
我用你的代码创建了一个 Dispossable class(有一些变化),并填充了缺失的方法和 运行 没有问题,没有挂起。我在 winform 应用程序中测试。
我从按钮调用方法并从一个文本框中复制,然后将值粘贴到另一个文本框中,粘贴的结果是有效的,没有挂起。
请注意我是如何通过使 class 继承自 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);
}
我一直在开发一个使用鼠标和键盘模拟的程序,并且经常需要 grab/set 剪贴板数据。
我已经 运行 解决了这个问题,显然很多人都遇到过,剪贴板正在被另一个进程使用,所以 "Clipboard.SetDataObject" 抛出异常 "Requested Clipboard operation did not succeed."
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);
}
}
我尝试了一些如上面代码所示的解决方案,但最终错误再次弹出。这次我决定全力以赴,并使用剪贴板获取进程的进程名称。
这是控制台显示的内容:
Process using Clipboard: Idle
Idle.exe 如何使用剪贴板?
我什至可以终止该进程以释放剪贴板吗?
我做错了什么吗?
归根结底,我只想能够无故障地进行剪贴板操作。 Ctrl+c 和 Ctrl+v 永远不会失败,为什么我的 C# 代码会失败?
更多信息:
我传递到剪贴板的数据是“-0.09261441”或类似的数字。
错误总是发生在 catch{...} 部分。
[已解决] 多亏了汉斯,我才能够弄明白。 我误解了 pinvoke 上的提示和示例代码。 try{}catch{} 中的这两个剪贴板操作在某种程度上显然是冲突的。正确的方法是使用 try{}catch{try{}catch{}} ,我没有使用也没有测试。
当我注释掉第二个剪贴板操作时,我的问题似乎暂时自行解决了。
我用你的代码创建了一个 Dispossable class(有一些变化),并填充了缺失的方法和 运行 没有问题,没有挂起。我在 winform 应用程序中测试。
我从按钮调用方法并从一个文本框中复制,然后将值粘贴到另一个文本框中,粘贴的结果是有效的,没有挂起。 请注意我是如何通过使 class 继承自 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);
}