2015-08-04 6 views
2

У меня есть приложение, которое снимает скриншоты с локального компьютера. Это работает много лет назад, пока вдруг коллега не сообщил мне, что он получил ошибку «Недопустимый дескриптор» из моего приложения.Graphics.CopyFromScreen() и GetDC (0) завершают работу с «Недопустимый дескриптор»

Эта ошибка исходила из среды .NET с Graphics.CopyFromScreen().

Чтобы обойти это, я заменил эту функцию кодом C++, используя GetDC(GetDesktopWindow())/GetDC(NULL) и BitBlt(), чтобы скопировать экран в растровое изображение. Теперь я получил ERROR_INVALID_HANDLE.

Это происходит на Windows 7.

Что там происходит? Я не могу самостоятельно расследовать эту проблему, потому что я не могу ее воспроизвести, а мой коллега находится в другой стране.

Я искал в Google, и многие люди сообщают об этой ошибке. Но все сообщения, которые я нашел, были от людей, которые пытались сделать снимок экрана с клиентского компьютера через код ASP на сервере. Я не понимаю, как люди могут испытывать странное желание захватить компьютер клиента с веб-сайта. Очевидно, что это не сработает.

Но я не мог найти ни одного случая, когда кто-то сообщает об этой проблеме из приложения, которое не может захватить экран этого же компьютера в сеансе SAME, в котором работает приложение.

+0

Это исключение почти всегда вызвано утечкой рукоятки, программа падает, когда ОС не позволяет процессу создавать больше или выгружается рабочая куча. Довольно диагностируется с помощью Диспетчера задач, вкладка «Процессы». Используйте «Вид»> «Выбрать столбцы» и отметьте «Пользовательские объекты» и «Объекты GDI». Устойчиво поднимающиеся числа заклинания обрекаются. –

+0

Кажется, вы не читали мой ответ. – Elmue

+0

Удаленные сеансы рабочего стола делят ваш экран. Это означает, что когда вы, например, сворачиваете приложение удаленного рабочего стола, больше нет экрана для захвата. Вы уверены, что проблема на самом деле происходит * все время? Он должен работать нормально, когда вы правильно подключены и когда приложение удаленного рабочего стола видимо и активно. Возможно, вам просто нужно обработать отказ изящно и возобновить работу, когда вы снова получите экран? – Luaan

ответ

3

После того как я проверил больше с моим коллегой и дал ему идеи, что он может попробовать, он сказал мне, что он запускает мое приложение через сеанс удаленного рабочего стола.

Сеанс удаленного рабочего стола создает виртуальный рабочий стол (вы видите, например, что обои для рабочего стола отсутствуют).

Я сказал своему коллеге, чтобы установить клиент 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, она работает. Таким образом, возможно, есть дополнительные системные настройки или другие факторы, которые вызывают ошибку «Ошибка дескриптора» (пакеты обновления/исправления ...?).

Но мой коллега сообщает, что он никогда не видел ошибки снова после того, как он прекратил использовать подключение к удаленному рабочему столу.

+0

Ваш ответ немного напоминает продвижение для TightVNC. Если это в настоящее время и в будущем не станет единственным программным обеспечением, которое когда-либо будет действовать, как вы описываете, то вы должны сделать его более универсальным. Я не сторонник. Кроме того, вы никогда не можете сказать, почему у кого-то есть. Я даже сделал это несколько раз по ошибке. Разочарование, но лучше всего двигаться дальше. Если вы можете сделать ответ более общим, есть награда. –

+0

Я не писатель TightVNC. Но если кто-то ищет альтернативу сеансу удаленного рабочего стола, почему бы сразу не дать ему решение, доказано, что оно работает? Я не вижу, что не так, чтобы привести рабочее решение. Я не уверен, работают ли все клиенты VNC одинаково. – Elmue

+0

Включите в вопрос вопрос «Я не уверен ...». Есть намерение, и есть то, на что это может быть похоже на других, независимо от намерения. Другая проблема заключается в том, что с ответом некоторые могут рассматривать это как вопрос «рекомендации по программному обеспечению» для закрытия. Поскольку люди, которые действительно хотят продвигать клиентов VNC, тратят Интернет, они найдут ваш вопрос и опубликуют свой спам. Это сложно. –

1

Есть несколько причин, по которым это может произойти, но основная тема заключается в том, что окно рабочего стола недоступно при вызове этого метода.

В дополнение к причинам, упомянутым выше, может возникнуть другая причина, по которой этот метод вызывается, когда экран заблокирован.

Код для 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 или недоступного рабочего окна - это прецедент, который должен быть обработан, чтобы приложение не разбилось.

Смежные вопросы