Сделайте скриншот внешней игры OpenGL C # с BitBlt (CopyFromScreen) - PullRequest
2 голосов
/ 19 октября 2019

Я пытаюсь создать какой-то античит для игры Counter Strike (HL). Конечно, функция создания скриншота в игре встроена, но используется приложениями Antyss, поэтому каждый раз, когда снимок экрана берется из игры, Antyss отключает читы (чтобы на скриншотах не было читов)

За последние несколько дней я прочитал десятки тем по этой теме. Большинство из них устарели и используют библиотеки, которые сейчас устарели.

Я читал о подходе с драйвером mirage (который не работает в Windows 10), о внедрении в приложение (конечно,приложение / игра не является частью моего кода) и использование / включение некоторого кода с библиотекой OPEN GL / D3D (для чтения backbuffer). Возможно, в конечном итоге это могло быть единственным решением.

Но сейчас у меня есть почти рабочее решение. Я пишу «почти», потому что он работает, но дает мне только некоторые «кэшированные» данные. Это дает мне правильный снимок экрана, но если я сделаю еще один снимок экрана - будет сделан тот же снимок экрана, что и в прошлый раз. Если, находясь в игре, я сверну приложение (полноэкранный режим) и вернусь к игре, на новом снятом скриншоте будет обновленный скриншот, но опять же, следующий скриншот будет точно таким же.

Я не знаю, является ли это "разработкой" или это "какая-то ошибка". Тем не менее, мой вопрос таков: могу ли я как-то форсировать эту "перезагрузку" без необходимости программно вызывать какую-то "alt + tab""и затем снова сосредоточиться на приложении?

В этой теме: Как делать скриншоты игры с OpenGL

@ Andon M. Coleman писал:

Вы на Windows? В полноэкранном режиме, начиная с Windows Vista, возникают проблемы со всем, что пытается захватить передний буфер (включая встроенный Alt + PrintScreen). Самое простое решение - изменить поведение буфера обмена на Копировать своп (PFD_SWAP_COPY, медленнее, но гарантированно работает). Часто, если вы нажмете Alt + TAB и вернетесь после переключения в полноэкранный режим, это тоже исправит это;хотя я никогда не мог объяснить это;) Если вы не написали игру в вопросе, то второе решение может быть вашим единственным выбором, если вы хотите использовать этот код.

Этоименно проблема, с которой я сталкиваюсь. Как он писал: «Alt + Tab» устраняет проблему (хотя он не знал, является ли это функцией или ошибкой). Он предложил изменить поведение замены буфера на Copy Swap (PFD_SWAP_COPY). Любые советы о том, как изменить мой код. с этим также будет очень приятно (я могу попробовать это), но если я правильно понял, этот подход является жизнеспособным решением, только если вы можете изменить это в игре (и это не мой случай)

Здесьмой рабочий код (который в темах о таких сценариях утверждал, что в этом подходе снимок экрана ЧЕРНЫЙ. Но он работает для меня)

private const int SW_RESTORE = 9;
public void TakeScreenShot()
{
    var guid = Guid.NewGuid();
    string procName = "hl";
    Process proc;

    try
    {
        proc = Process.GetProcessesByName(procName)[0];
    }
    catch (IndexOutOfRangeException e)
    {
        return;
    }


    // Focus on the application
    SetForegroundWindow(proc.MainWindowHandle);
    ShowWindow(proc.MainWindowHandle, SW_RESTORE);

    Thread.Sleep(1000);

    Rect rect = new Rect();
    IntPtr error = GetWindowRect(proc.MainWindowHandle, ref rect);

    while (error == (IntPtr)0)
    {
        error = GetWindowRect(proc.MainWindowHandle, ref rect);
    }

    int width = rect.right - rect.left;
    int height = rect.bottom - rect.top;

    using (Bitmap printscreen = new Bitmap(width, height, PixelFormat.Format32bppArgb))
    {
        using (var graphics = Graphics.FromImage(printscreen))
        {
            graphics.CopyFromScreen(rect.left,
                                               rect.top,
                                               0,
                                               0,
                                               new Size(width, height),
                                               CopyPixelOperation.SourceCopy);
            printscreen.Save($@"{Path.GetTempPath()}\{guid.ToString()}.jpg", ImageFormat.Jpeg);
        }
    }
}

Я хочу, чтобы это приложение работало в Windows7, Windows8, Windows10. Лучше всего было бы охватить полноэкранный и оконный режим (но полноэкранный режим, вероятно, важнее)

Любой совет, как поступить (или почему я получаю «кэшированные» данные), был бы хорош:)

Конечно, если кто-то скажет (с полным правом), что то, чего я хочу достичь, невозможно с помощью CopyFromScreen (и нет взломаКроме того, помимо минимизации и максимизации экрана) я рассмотрю вариант внедрения кода. Но обычно я хотел бы держаться подальше от этого, так как это можно рассматривать как обман и может привести к бану VAC.

====== ОБНОВЛЕНИЕ ======

Вы можете попытаться воспроизвести процесс создания скриншота, загрузив игру (небольшая, 260 МБ): https://cssetti.pl/Api/GameDownload.php?GameDownloadId=v43

Затем вы можете скопировать и вставить мой код в Linqpad (или любой другой редактор) и запуститькод. Приложение после запуска запустит процесс HL, который затем используется для получения снимка экрана.

====== ОБНОВЛЕНИЕ 2 ======

В режиме Windows все работает правильно (на экранах печати все в порядке)

...