Запретить общий доступ к рабочему столу определенной формы win # или обнаружить общий доступ к рабочему столу - PullRequest
11 голосов
/ 25 мая 2019

При разработке экзаменационного программного обеспечения у меня есть требование запретить общий доступ к рабочему столу с помощью таких приложений, как TeamViewer, AnyDesk, Ammyy Admin и т. Д. Или, по крайней мере, его обнаружение. Наше экзаменационное программное обеспечение разработано на C #, это winform, задает вопрос один за другим.

Я не думаю, что обнаружение так просто, так как существует множество способов захвата экрана Desktop Duplication API, BitBlt, Direct3D, DirectX, DirectShow и многих других.

Итак, я начал изучать, как предотвратить отображение формы c # win при запуске общего доступа к рабочему столу. Для этого я попробовал следующее:

  1. Поскольку наше приложение будет работать в Windows 7 и выше, поэтому я воспользовался DWM (Destop Window Manager), проверив композицию рабочего стола, и я установил SetWindowDisplayAffinity в WDA_MONITOR, чтобы включить защиту для моей winform. Делая это, когда я когда-либо начинаю общий доступ к рабочему столу, компьютер, который использовал удаленный доступ, может видеть черный слой поверх формы. Но не все приложения для совместного использования рабочего стола имеют одинаковое поведение. Как TeamViewer ведет себя так, как ожидалось, а Ammyy Admin, AnyDesk - нет. Как некоторые приложения показывают черный слой, а некоторые нет? Могу ли я что-нибудь сделать дополнительно?
if (winForm != null)
{
    if (Protect)
        result = SetWindowDisplayAffinity(winForm.Handle, WDA_MONITOR);
    else
        result = SetWindowDisplayAffinity(winForm.Handle, WDA_NONE);
}

этот подход, который я кодировал, не является полным доказательством для всех приложений общего доступа к рабочему столу, так есть ли какое-либо 100% решение для предотвращения / обнаружения общего доступа к рабочему столу?

Если вы опробовали видеовыход DirectX (DirectDraw) для VLC-плеера, то этот метод вывода также делает то же самое, что и SetWindowDisplayAffinity, он добавляет черный слой на видео при запуске любого приложения для совместного использования на рабочем столе, и я протестировал это работает почти с 9 приложениями для совместного использования рабочего стола, есть идеи, как это сделать? и можно ли это сделать с помощью c # winform?

Обновление 29-05-2019

После проверки кода VLC я узнал, что они используют аппаратное наложение с использованием DirectDraw. Итак, я создал проект vc ++ и использовал d3d9 и создал оверлей с поверхностью красного цвета, теперь, если я возьму удаленный компьютер, то форма с красным цветом покажет черный цвет. Бинго!! половина проблемы решена.

Теперь я пытаюсь установить прозрачность для этого окна, чтобы поверх моего приложения на C # было наложение, и кандидат может сдать экзамен, а если удаленный объект выбран, то наложение будет показано черным цветом. Чтобы сделать окно прозрачным, я использовал DwmExtendFrameIntoClientArea winapi, но теперь на пульте он также виден как прозрачный. Есть ли выход для этого?

1 Ответ

3 голосов
/ 31 мая 2019

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

Сначала я хотел бы прояснить, как работает VLC "DirectX (DirectDraw) видео выход"? Этот конкретный режим вывода VLC использует DirectDraw для создания аппаратного оверлея, и на нем воспроизводится видео. Во время захвата экрана (не с мобильной или внешней камеры) большая часть механизма захвата захватывает экран, запрашивая GDI для экранов, но аппаратные оверлеи накладываются непосредственно на GPU, и GDI не может получить доступ к GPU. Это как GDI-> CPU + RAM, DirectX-> GPU + VRAM, поэтому при захвате экрана VLC воспроизводящая видео часть отображается черным. Для получения дополнительной информации https://stackoverflow.com/a/21535254/1629242

Но как РоманР. упомянутое в чате "использование наложения, предназначенного для видео, НЕ поможет скрыть пользовательский интерфейс приложения".

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

Риддел выдвинул новую идею о том, «как работают антивирусы и проходит через все процессы и проверяет хэш-инструменты для общих средств совместного использования экрана», но я лично считаю, что это не будет универсальным решением, так как я должен вести список таких приложений. и это хеш, также, если какие-либо новые приложения найдены, обновите этот список. Кроме того, любой может редактировать байты, чтобы разбить хэши, чтобы сделать это ложным.

Решение, которое я принял:

Windows API предоставляет функцию, которая помогает отображать содержимое окна только на мониторе. то есть SetWindowDisplayAffinity, это работает как шарм !!

проблема с минимально поддерживаемой ОС:

Хотя в документе MSDN упоминается «Минимально поддерживаемый клиент :: Windows 7», но в Windows 7 он работает не для всех приложений захвата экрана. RomanR. говорится в комментарии: «Это будет работать правильно, начиная с Windows 8 (и, возможно, также с обновлением платформы для Windows 7). На чистой Windows 7 вы получаете бесплатный общий доступ к рабочему столу и не можете защитить свой контент».

Так что в настоящее время я закончил с SetWindowDisplayAffinity Я реализовал это как:

private const uint WDA_NONE = 0x0;
private const uint WDA_MONITOR = 0x1;

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SetWindowDisplayAffinity(IntPtr hWnd, uint dwAffinity);

public static bool SetDRM(Form winForm, bool Protect)
{
    bool result = false;
    if (winForm != null)
    {
        if (Protect)
            result = SetWindowDisplayAffinity(winForm.Handle, WDA_MONITOR);
        else
            result = SetWindowDisplayAffinity(winForm.Handle, WDA_NONE);
    }
    return result;
}
...