5 Stimmen

Wie macht man einen Screenshot mit Mono C#?

Ich versuche, einen Screenshot in Mono C# zu erstellen, aber ich erhalte eine System.NotImplementedException, wenn ich den Code CopyFromScreen . Mein Code funktioniert mit .NET, gibt es also eine alternative Möglichkeit, einen Screenshot mit Mono zu erstellen?

Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics graphics = Graphics.FromImage(bitmap as Image);
graphics.CopyFromScreen(0, 0, 0, 0, bitmap.Size);
System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
bitmap.Save(memoryStream, imageFormat);
bitmap.Save(@"\tmp\screenshot.png", ImageFormat.Png);

Ich verwende Mono JIT Compiler Version 2.4.2.3 (Debian 2.4.2.3+dfsg-2)

UPDATE: Mono kann keine Bildschirmfotos machen. Traurig. Lahm.

1 Stimmen

Bitte geben Sie in Ihrer Frage die Version von Mono an, die Sie derzeit verwenden.

0 Stimmen

Ich bin gerade nicht an meinem Computer, aber wenn ich die Versionsnummer angeben soll, bedeutet das, dass das Problem in einer neueren Version als der von mir verwendeten behoben wurde?

0 Stimmen

Ich verwende Mono JIT Compiler Version 2.4.2.3 (Debian 2.4.2.3+dfsg-2)

6voto

serge_gubenko Punkte 19568

Ich denke, eine Alternative wäre die Verwendung von gtk#, um einen Screenshot zu erhalten. Sie müssten ein Mono-Projekt mit GTK#-Unterstützung erstellen, danach sollte der folgende Code ausgeführt werden:

Gdk.Window window = Gdk.Global.DefaultRootWindow;
if (window!=null)
{           
    Gdk.Pixbuf pixBuf = new Gdk.Pixbuf(Gdk.Colorspace.Rgb, false, 8, 
                                       window.Screen.Width, window.Screen.Height);          
    pixBuf.GetFromDrawable(window, Gdk.Colormap.System, 0, 0, 0, 0, 
                           window.Screen.Width, window.Screen.Height);          
    pixBuf.ScaleSimple(400, 300, Gdk.InterpType.Bilinear);
    pixBuf.Save("screenshot0.jpeg", "jpeg");
}

können Sie auch P \Invoke und rufen GTK-Funktionen direkt auf.

Ich hoffe, das hilft Ihnen, viele Grüße

0 Stimmen

Danke. es scheint, dass Mono selbst nicht in der Lage ist, einen Screenshot zu machen. ich bin wirklich enttäuscht. gut, dass ich dies früh in meinem Projekt gefunden habe, sieht aus wie Java hier ich komme... verdammt.

0 Stimmen

Vielleicht möchten Sie auch einen Blick auf C++ werfen \python + QT, wenn Sie ein plattformübergreifendes Entwicklungs-Framework suchen

2voto

Evgenyt Punkte 9413

Wir hatten das gleiche Problem, als wir mit Mono unter Linux und OS X in derselben Software Screenshots machen wollten.

Tatsächlich können Sie CopyFromScreen auf Mono unter Linux. Sie müssen jedoch das Paket mono-complete installieren, das System.Drawing enthält.

Für OS X Die zuverlässigste Methode ist Process.Start der screencapture Kommandozeilenprogramm. Es ist dort standardmäßig vorhanden.

Für Linux Um es zuverlässig zu machen, kann man entweder import Befehlszeile von ImageMagic (in diesem Fall müssen Sie es zu einer Abhängigkeit machen), oder erzwingen Sie die Abhängigkeit von mono-complete Paket, das System.Drawing enthält. Gtk#-Ansatz ist nach unseren Tests unzuverlässig und kann leere Bildschirme liefern oder mit Ausnahmen fehlschlagen (und wir machen jeden Tag Tausende von Screenshots auf verschiedenen Rechnern).

Außerdem müssen Sie, wenn Sie mehrere Bildschirme in einem Screenshot erfassen wollen, die einzelnen Screenshots richtig ausrichten, nachdem Sie sie mit CopyFromScreen separat aufgenommen haben.

Wir haben also bisher diese Lösung:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Windows.Forms;

namespace Pranas
{
    /// <summary>
    ///     ScreenshotCapture
    /// </summary>
    public static class ScreenshotCapture
    {
        #region Public static methods

        /// <summary>
        ///     Capture screenshot to Image object
        /// </summary>
        /// <param name="onlyPrimaryScreen">Create screen only from primary screen</param>
        /// <returns></returns>
        public static Image TakeScreenshot(bool onlyPrimaryScreen = false)
        {
            try
            {
                return WindowsCapture(onlyPrimaryScreen);
            }
            catch (Exception)
            {
                return OsXCapture(onlyPrimaryScreen);
            }
        }

        #endregion

        #region  Private static methods

        //private static Image ImageMagicCapture(bool onlyPrimaryScreen)
        //{
        //  return ExecuteCaptureProcess("import", "-window root ");
        //}

        private static Image OsXCapture(bool onlyPrimaryScreen)
        {
            var data = ExecuteCaptureProcess(
                "screencapture",
                string.Format("{0} -T0 -tpng -S -x", onlyPrimaryScreen ? "-m" : ""));
            return data;
        }

        /// <summary>
        ///     Start execute process with parameters
        /// </summary>
        /// <param name="execModule">Application name</param>
        /// <param name="parameters">Command line parameters</param>
        /// <returns>Bytes for destination image</returns>
        private static Image ExecuteCaptureProcess(string execModule, string parameters)
        {
            var imageFileName = Path.Combine(Path.GetTempPath(), string.Format("screenshot_{0}.jpg", Guid.NewGuid()));

            var process = Process.Start(execModule, string.Format("{0} {1}", parameters, imageFileName));
            if (process == null)
            {
                throw new InvalidOperationException(string.Format("Executable of '{0}' was not found", execModule));
            }
            process.WaitForExit();

            if (!File.Exists(imageFileName))
            {
                throw new InvalidOperationException(string.Format("Failed to capture screenshot using {0}", execModule));
            }

            try
            {
                return Image.FromFile(imageFileName);
            }
            finally
            {
                File.Delete(imageFileName);
            }
        }

        /// <summary>
        ///     Capture screenshot with .NET standard implementation
        /// </summary>
        /// <param name="onlyPrimaryScreen"></param>
        /// <returns>Return bytes of screenshot image</returns>
        private static Image WindowsCapture(bool onlyPrimaryScreen)
        {
            if (onlyPrimaryScreen) return ScreenCapture(Screen.PrimaryScreen);
            var bitmaps = (Screen.AllScreens.OrderBy(s => s.Bounds.Left).Select(ScreenCapture)).ToArray();
            return CombineBitmap(bitmaps);
        }

        /// <summary>
        ///     Create screenshot of single display
        /// </summary>
        /// <param name="screen"></param>
        /// <returns></returns>
        private static Bitmap ScreenCapture(Screen screen)
        {
            var bitmap = new Bitmap(screen.Bounds.Width, screen.Bounds.Height, PixelFormat.Format32bppArgb);

            using (var graphics = Graphics.FromImage(bitmap))
            {
                graphics.CopyFromScreen(
                    screen.Bounds.X,
                    screen.Bounds.Y,
                    0,
                    0,
                    screen.Bounds.Size,
                    CopyPixelOperation.SourceCopy);
            }

            return bitmap;
        }

        /// <summary>
        ///     Combine images into one bitmap
        /// </summary>
        /// <param name="images"></param>
        /// <returns>Combined image</returns>
        private static Image CombineBitmap(ICollection<Image> images)
        {
            Image finalImage = null;

            try
            {
                var width = 0;
                var height = 0;

                foreach (var image in images)
                {
                    width += image.Width;
                    height = image.Height > height ? image.Height : height;
                }

                finalImage = new Bitmap(width, height);

                using (var g = Graphics.FromImage(finalImage))
                {
                    g.Clear(Color.Black);

                    var offset = 0;
                    foreach (var image in images)
                    {
                        g.DrawImage(image,
                            new Rectangle(offset, 0, image.Width, image.Height));
                        offset += image.Width;
                    }
                }
            }
            catch (Exception ex)
            {
                if (finalImage != null)
                    finalImage.Dispose();
                throw ex;
            }
            finally
            {
                //clean up memory
                foreach (var image in images)
                {
                    image.Dispose();
                }
            }

            return finalImage;
        }

        #endregion
    }
}

Oder installieren Sie es über NuGet ( Haftungsausschluss: Ich bin der Autor ) :

PM> Install-Package Pranas.ScreenshotCapture

Wir verwenden es in unserem Produkt in vielen Konfigurationen, daher verbessern wir regelmäßig den Code und fügen Hinweise in Blog .

0voto

Franz Punkte 21

Mit Mono 2.4.4 können Sie den ganzen Bildschirm sehen sin GTK#:

public static class MonoScreenShooter { public static void TakeScreenshot(string filePath) { using (Bitmap bmpScreenCapture = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)) { using (Graphics g = Graphics.FromImage(bmpScreenCapture)) { g.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, bmpScreenCapture.Size, CopyPixelOperation.SourceCopy); } bmpScreenCapture.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg); } } } }

0 Stimmen

Sind Sie sicher, über diesen Code?... Ich erhalte die gleiche System.NotImplementedException

0 Stimmen

Sie müssen System.Drawing haben. Das Paket mono-complete unter Linux sollte funktionieren. Unter Mac OS X müssen Sie PInvoke verwenden (unzuverlässig und komplex), oder Sie starten einfach screencapture Werkzeug. Siehe meine Antwort für Details

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X