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

Elm*_*mue 4 c# c++ screenshot

我有一个从本地计算机获取屏幕截图的应用程序。自从多年以来,这种方法一直有效,直到一个同事突然告诉我他从我的应用程序中收到“句柄无效”错误。

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

要解决这个我用C ++代码此功能使用替换GetDC(GetDesktopWindow())/ GetDC(NULL)BitBlt()屏幕复制到一个位图。现在我得到了ERROR_INVALID_HANDLE

在Windows 7上会发生这种情况。

那是怎么回事?我无法独自研究此问题,因为我无法重现此问题,并且我的同事在另一个国家。

我在Google中搜索,很多人报告此错误。但是我发现的所有帖子都来自试图通过服务器上的ASP代码从客户端计算机获取屏幕截图的人员。我不明白人们怎么会有从网站捕获客户计算机的奇怪愿望。显然,这是行不通的。

但是我无法找到一种情况,即有人从无法在运行应用程序本身的SAME会话中捕获SAME计算机屏幕的应用程序报告此问题。

Elm*_*mue 6

After investigating more with my colleague and giving him ideas what he can try, he told me that he starts my application through a remote desktop session.

The remote desktop session creates a virtual desktop (you see for example that the desktop wallpaper is missing).

I told my colleague to install a VNC client to remote control the computer instead of a remote desktop session and now all works fine. He installed TightVNC which uses the REAL desktop user session instead of creating a virtual session and locking the screen of the machine.

So if anyone gets reports of "The handle is invalid" while taking a screen capture, ask your users if they use a remote desktop session.

To detect a remote desktop session in code you can write:

in C++:

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

or in C#:

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

Note that the problem is not reproducible on all computers. When I test on my own Windows 7 it works. So there are probably any additional system settings or other factors that trigger the "The handle is invalid" error (service packs / hotfixes...?).

But my colleague reports that he has never seen the error again after he stopped using the remote desktop connection.


Ste*_*don 5

发生这种情况的原因有很多,但潜在的主题是调用此方法时桌面窗口不可用。

除了上述原因外,发生这种情况的另一个原因是在锁定屏幕时是否正在调用此方法。

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();
}
Run Code Online (Sandbox Code Playgroud)

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