Graphics.CopyFromScreen()和GetDC(0)失败并显示“句柄无效”

时间:2015-08-04 16:09:40

标签: c# c++ screenshot

我有一个从本地计算机截取屏幕截图的应用程序。 多年以来这一点正常工作,直到一位同事突然报告我他的应用程序出现“句柄无效”错误。

此错误来自Graphics.CopyFromScreen()的.NET框架内部。

要解决此问题,我使用GetDC(GetDesktopWindow()) / GetDC(NULL)BitBlt()将此函数替换为C ++代码,将屏幕复制到位图中。现在我得到ERROR_INVALID_HANDLE

这种情况发生在Windows 7上。

那里发生了什么? 我不能自己调查这个问题,因为我无法重现它,我的同事也在另一个国家。

我在谷歌搜索过很多人报告此错误。 但我发现的所有帖子都来自试图通过服务器上的ASP代码从客户端计算机截取屏幕截图的人。我不明白人们如何从网站上捕获客户端计算机的奇怪愿望。很明显,这不起作用。

但我找不到一个案例,有人从应用程序报告此问题,该应用程序无法在应用程序本身运行的SAME会话中捕获SAME计算机的屏幕。

2 个答案:

答案 0 :(得分:4)

在与我的同事进行更多调查并向他提出他可以尝试的想法之后,他告诉我他通过远程桌面会话启动我的应用程序。

远程桌面会话会创建一个虚拟桌面(例如,您会看到缺少桌面墙纸)。

我告诉我的同事安装VNC客户端来远程控制计算机而不是远程桌面会话,现在一切正常。他安装了TightVNC,它使用REAL桌面用户会话而不是创建虚拟会话并锁定机器的屏幕。

因此,如果有人在拍摄屏幕时收到“手柄无效”的报告,请询问您的用户是否使用远程桌面会话。

要在代码中检测远程桌面会话,您可以编写:

在C ++中:

if (GetSystemMetrics(SM_REMOTESESSION) > 0)
{
    MessageBox(m_hWnd, L"This application may not work correctly in a remote desktop session", "Error", MB_ICONSTOP);
}

或在C#中:

if (System.Windows.Forms.SystemInformation.TerminalServerSession)
{
    Messagebox.Show("This application may not work correctly in a remote desktop session");
}

请注意,所有计算机上的问题都无法重现。当我在自己的Windows 7上进行测试时,它可以工作。因此可能有任何其他系统设置或其他因素触发“句柄无效”错误(Service Pack / hotfixes ...?)。

但是我的同事报告说他在停止使用远程桌面连接后再也没有看到错误。

答案 1 :(得分:3)

这可能会发生一些原因,但基本主题是调用此方法时桌面窗口不可用。

除了上面提到的原因之外,另一个可能发生的原因是当屏幕被锁定时调用此方法。

CopyFromScreen的代码包含以下部分:

int result = SafeNativeMethods.BitBlt(targetDC, destinationX, destinationY, destWidth, destHeight, screenDC, sourceX, sourceY, (int) copyPixelOperation); 

//a zero result indicates a win32 exception has been thrown
if (result == 0) { 
    throw new Win32Exception();
}

在我看来,最安全的做法是,如果您使用此功能,请确保您也编写代码,假设接收Win32Exception或不可用的桌面窗口是必须的用例处理所以应用程序不会崩溃。