Graphics.CopyFromScreen() и GetDC(0) завершаются с ошибкой "Дескриптор недействителен"
У меня есть приложение, которое делает снимки экрана с локального компьютера. Это работает правильно много лет, пока вдруг коллега не сообщил мне, что он получил сообщение "Неверный дескриптор" из моего приложения.
Эта ошибка произошла из.NET Framework из Graphics.CopyFromScreen()
,
Чтобы обойти это, я заменил эту функцию на код C++, используя GetDC(GetDesktopWindow())
/ GetDC(NULL)
а также BitBlt()
скопировать экран в растровое изображение. Теперь я получил ERROR_INVALID_HANDLE
,
Это происходит в Windows 7.
То, что там происходит? Я не могу исследовать эту проблему самостоятельно, потому что я не могу воспроизвести ее, и мой коллега находится в другой стране.
Я искал в Google, и многие люди сообщают об этой ошибке. Но все сообщения, которые я нашел, были от людей, которые пытались сделать снимок экрана с клиентского компьютера через код ASP на сервере. Я не понимаю, как люди могут иметь странное желание захватить компьютер клиента с веб-сайта. Очевидно, что это не будет работать.
Но я не смог найти ни одного случая, когда кто-нибудь сообщил об этой проблеме из приложения, которое не может сделать снимок экрана того же компьютера в том же сеансе, где само приложение работает.
2 ответа
После более подробных исследований с моим коллегой и предоставления ему идей о том, что он может попробовать, он сказал мне, что запускает мое приложение через сеанс удаленного рабочего стола.
Сеанс удаленного рабочего стола создает виртуальный рабочий стол (например, вы видите, что обои рабочего стола отсутствуют).
Я сказал своему коллеге установить клиент VNC для удаленного управления компьютером вместо сеанса удаленного рабочего стола, и теперь все работает нормально. Он установил TightVNC, который использует пользовательский сеанс РЕАЛЬНОГО рабочего стола вместо создания виртуального сеанса и блокировки экрана машины.
Поэтому, если кто-то получит отчеты "Дескриптор недействителен" во время захвата экрана, спросите своих пользователей, используют ли они сеанс удаленного рабочего стола.
Чтобы обнаружить сеанс удаленного рабочего стола в коде, вы можете написать:
в 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, это работает. Таким образом, возможно, имеются какие-либо дополнительные системные настройки или другие факторы, которые вызывают ошибку "Неверный дескриптор" (пакеты обновления / исправления...?).
Но мой коллега сообщает, что больше никогда не видел ошибку после того, как перестал использовать подключение к удаленному рабочему столу.
Это может произойти по нескольким причинам, но основная тема заключается в том, что окно рабочего стола недоступно при вызове этого метода.
В дополнение к причинам, упомянутым выше, еще одна причина, по которой это может произойти, - это когда этот метод вызывается, когда экран заблокирован.
Код для 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 или недоступное окно рабочего стола является вариантом использования, который должен обрабатываться, чтобы приложение не падает.