SlimDX & directX Screenshot

  • C#
  • .NET (FX) 4.0

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von GooMan.

    Servus,

    ich hatte mal n' Testprogramm geschrieben welches z.B von Battlefield nen Screen gemacht hatte (ohne Inject). Ich weis nicht ob das zutrifft aber hier der Code der mir geholfen hat:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim oBitmap As Bitmap
    3. ' Objekte für Ausdruck/Seitenvorschau
    4. Dim WithEvents PrintDocument As New Printing.PrintDocument
    5. Dim PrintPreview As New PrintPreviewDialog
    6. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    7. 'shows a cpmplete Printscreen
    8. Dim ScreenSize As Size = New Size(My.Computer.Screen.Bounds.Width, My.Computer.Screen.Bounds.Height)
    9. Dim BMP As New Bitmap(My.Computer.Screen.Bounds.Width, My.Computer.Screen.Bounds.Height)
    10. Dim g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(BMP)
    11. g.CopyFromScreen(New Point(0, 0), New Point(0, 0), ScreenSize)
    12. Dim FileDir0 As String = "C:\" 'FileDIR.Text
    13. Dim Frame As String = "Num1" 'FileNum.Text
    14. Dim IMG As String = ".jpg" 'FileType.Text
    15. BMP.Save(FileDir0 + Frame + IMG)
    16. PictureBox1.Load(FileDir0 & Frame & IMG)
    17. End Sub
    18. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    19. 'SendKeys.Send("% {PRTSC} ")
    20. ' Screenshot des aktiven Fensters erstellen
    21. SendKeys.Send("%({PRTSC})")
    22. SendKeys.Flush()
    23. ' Bitmap-Objekt aus Zwischenablage kopieren
    24. oBitmap = CType(Clipboard.GetImage(), Bitmap)
    25. PictureBox1.Image = oBitmap
    26. 'Not asked in your quetion
    27. ' in Seitenvorschau anzeigen
    28. 'With PrintPreview
    29. '.Document = PrintDocument
    30. '.ShowDialog()
    31. ' End With
    32. End Sub
    33. End Class


    Da das schon ne Weile her ist habe ich meine Snippets nicht mehr. Aber hier die Quelle zu dem Code von oben.
    Vielleicht hilfts ja
    Gruß

    Wow erstma danke für die Antwort!

    Dann ist der Code für VB aber nutze C#. Kein Ding kann es ja umkonvertieren.. ABER dann kommt da ein große Entscheidung:

    Das ganze nutzt ja ansich nur die PrintScreen Funktion von Windows, welche nicht der Weg ist den ich gehen möchte. Da es für mein Bildhoster Program ist ist das leider ein uneleganter weg, den ich erst gehen möchte wenn alles was ich versucht habe Fehlschlägt. Ich behalte deine Option im Hinterkopf, möchte sie aber eigentlich nicht verwenden. Trotzdem danke das du geantwortet hast. Bedeutet mir viel da, zu meinen Themen sonst keiner Antwortet :P.
    Ja hatte den fertigen auch in C# geschrieben nur leider alles weg..
    Aber zu deiner Aussage dass man gebannt wird hab ich was gegen. Z.B Fraps injected auch den Prozess soviel ich weis :P und z.B VAC (Valve Anticheat) ist nur auf die Cheats selber ausgerichtet. Sprich wenn (kenne mich da nur wage mit aus) Adressen des jeweiligen Spiels verändert werden, reagiert er. Bei einem Screenshot wird ja nichts verändert. Bei z.B einem Godmode oder was auch immer werden ja bestimme "Adressen" des Spiels verändert/Manipuliert.

    Sprich ist deine Methode relativ sicher.

    Hmm. Ja ich bin aber irgendwie lieber auf der Sicheren Seite. Will ja meine User nicht in Gefahr bringen.

    Zum Thema:

    Hab jetzt mal ein ScreenCapture Tool mit DirectX ausprobiert. Geht auch nicht. Crasht sobald ein Spiel im Vollbild läuft :/

    (codeproject.com/Articles/27446…e-using-DirectX-in-Csharp - D3DERR_INVALIDCALL: Invalid call (-2005530516))



    Ich hab langsam das gefühl das es ohne Injecten keine möglichkeit gibt :/

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „GooMan“ ()

    Seit Windows 8 gibt es ja eine neue Tastenkombination für Screenshots. Man könnte sich ja mal anschauen, wie die funktioniert, denn die sollte auch bei Spielen funktionieren.
    Von meinem iPhone gesendet
    Windows 8 installieren und etwas Reverse-Engineering betreiben. Eventuell findet man die funktionsweise auch schon im Internet. Alternativ kannst du auch bei MS nachfragen.
    Die Tastenkombination ist Win+Print Screen bzw. Win+Volume Down für Tablets.
    Von meinem iPhone gesendet
    Also im Web finde ich für DirectX / SlimDX keine möglichkeit OHNE Inject ein Bild zu machen. Wird auch nicht möglich sein.

    @nikeee13
    Ist eine gute Idee. Aber wäre hier wohl einfach zu Überdimensioniert.

    Ich bin zum entschluss gekommen einfach die Hooking Methode zu benutzen und alternative @BradApfel s Methode anzubieten. Ausserdem werde ich mich mal mit einem Spieleentwickler von einer großen Firma auseinander setzen ob dies PunkBuster blockt / bannt. @All vielen dank für eure Hilfe!
    Das isn Snippet von mir (glaube auch ausm Netz) schalte Aero aus

    C-Quellcode

    1. Process[] procs = Process.GetProcessesByName("bf3");
    2. IntPtr hWnd = IntPtr.Zero;
    3. foreach (Process prc in procs)
    4. {
    5. if (prc.MainWindowHandle != IntPtr.Zero)
    6. {
    7. hWnd = prc.MainWindowHandle;
    8. break;
    9. }
    10. }
    11. Device device = new Device(hWnd);
    12. Surface backbuffer = device.GetBackBuffer(0, 0, BackBufferType.Mono);
    13. SurfaceLoader.Save("Screenshot.bmp", ImageFileFormat.Bmp, backbuffer);
    14. backbuffer.Dispose();

    Also wenn Fenster im Hintergrund:
    Kein Fehler

    Wenn Fenster im Vollbild Vordergrund: DEVICE_LOST

    Mal schauen vielleicht gehts ja doch O_o

    @AliveDevil
    Auch interessant Danke! Werd ich mir mal anschauen!

    EDIT:

    @AliveDevil
    Benutzt auch Inject O_O

    Quellcode

    1. BOOL WINAPI InjectLibrary(HANDLE hProcess, CTSTR lpDLL)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „GooMan“ ()

    Ich habe mich mal ein bisschen in Windows umgeschaut.
    Das Screenshot-Ding unter Windows 8 liegt in der twinui.dll. Die Klasse dafür heißt CSceenShooter (dat Name). Das eigentliche Erstellen des Screenshots findet in CScreenShooter::_Grab statt.
    In dieser funktion passiert eigentlich nichts weiter als bei CopyFromScreen mit GDI+.

    In a nutshell (die eigentliche Vorgehensweise hat mehr Fehlerbehandlungen und Drumrum):

    C-Quellcode

    1. HDC screenDc = GetDC(0);
    2. HDC dc = CreateCompatibleDC(screenDc);
    3. Rect* rect;// Recangle des Bereiches
    4. int cx = rect->right - rect->left;
    5. int cy = rect->bottom - rect->top;
    6. HBITMAP bitmap = CreateCompatibleBitmap(screenDc, cx, cy);
    7. if(bitmap != null)
    8. {
    9. HGDIOBJ ha = SelectObject(dc, bitmap);
    10. BOOL success = BitBlt(dc, 0, 0, cx, cy, screenDc, rect->left, rect->top, SRCCOPY);
    11. }
    12. ReleaseDC(0, screenDc);
    13. DeleteDC(dc);


    Graphics.CopyFromScreen() funktionert AFAIK genauso. Vielleicht liegts einfach nur an den Parametern. Oder die Windows 8 Screenshot-Funktion funktioniert auch nicht bei DX-Spielen (habe ich auch noch nicht nachgeschaut).
    Von meinem iPhone gesendet

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „nikeee13“ ()

    Vielleicht wichtig zu wissen: es gibt zwei verschiedene Arten, einen Vollbildmodus umzusetzen, einerseits den DirectX-Vollbildmodus, andererseits den Windowed-Modus mit maximierter Form. Das sieht gleich aus, ist aber was komplett verschiedenes, denn beim ersten wird der komplette Bildschirm alleine von DirectX gezeichnet, beim zweiten wird immer noch der Desktop mit allen Fenster von Windows gezeichnet und DirectX zeichnet auf das Fenster (das halt den kompletten Bildschirm verdeckt). Ersteres kann nicht gescreenshotet werden, weil kein GDI-Device da ist, da bringen auch keine Win8-Tastenkombis irgend was (gerade ausprobiert), zweiteres schon.
    Du musst mal nachsccheuen, ob die in Frage kommenden Spiele eine entsprechende Einstellung dafür haben, bei StarCraft2 z.B. ist eine vorhanden:

    Artentus schrieb:

    einerseits den DirectX-Vollbildmodus, andererseits den Windowed-Modus mit maximierter Form
    Daran habe ich auch schon gedacht. Ich habe aber eine Hoffnung gehabt, dass man trotzdem via BitBlt an das Bild kommt.

    Man sollte auch irgendwie an den direkten Buffer des aktuellen Bildes kommen, also unabhängig von GDI und DX. Ohne irgendwelche Low-Level-Hooks ist das aber bestimmt nicht möglich.

    Zu Hooks:
    Ich glaube Fraps und diverse andere Screenshot/Screenrecorder-Software benutzen DX-Hooks. Hier hat Jemand dazu was geschrieben:
    stackoverflow.com/a/17840137/785210
    blog.nektra.com/main/2013/07/2…culate-frames-per-second/

    Laut dem Beitrag dort ist eine weitere Möglichkeit das Implementieren eines Mirror Drivers. Ich wünsche viel Spaß dabei. :P
    Von meinem iPhone gesendet
    Wieso so feindselig vorm injecten?
    Fraps injected auch in den Prozess rein um die Bilddaten vom Spiel zu bekommen, genauso wie PlayClaw 3 auch...
    Du wirst deswegen nicht gebannt, es sei denn es verändert die Memory, dann ist es auffälliger...
    Um zu injecten musst du zwangsweise die Memory verändern, deswegen verstehe ich deine Aussage nicht. Vac und gerade PunkBuster checken, ob Funktionen gehookt werden und das müssen sie auch, sonst wären es ja keine guten anti-cheat Programme. Die meisten Aufnahmeprogramme wie Fraps, arbeiten nach einem bestimmten Muster und/oder stehen auf Ausnahmelisten.