How to take a screenshot using Mono C #?

I am trying to use a usage code to get a screenshot in Mono C #, but I get a System.NotImplementedException when I call CopyFromScreen . My code works with .NET, so is there an alternative way to get a screenshot using Mono?

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); 

I am using the Mono JIT compiler version 2.4.2.3 (Debian 2.4.2.3 + dfsg-2)

UPDATE: Mono cannot take screenshots. Sad. Lame

+4
source share
3 answers

I guess an alternative would be to use gtk # to get a screenshot. You will need to create a monoproject with GTK # support, after which the following code should execute:

 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"); } 

you can also use P \ Invoke and directly access GTK functions.

hope this helps, believes

+3
source

We had the same problem when we needed to take screenshots from Mono on Linux and OS X in the same software.

Actually, you can use CopyFromScreen in Mono on Linux. However, you need to install a mono-complete package that includes System.Drawing.

For OS X, the process is the most reliable way. Run the screencapture command line tool. It is present there by default.

For Linux , to make it reliable, you can use either the import command line from ImageMagic (in which case you will need to make a dependency), or install a dependency on a mono-complete package that includes System.Drawing. The Gtk # approach is unreliable according to our tests and may contain empty screens or crash with an error (and every day we take thousands of screenshots on different machines).

Another thing is that when you need to capture multiple displays in one screenshot, you must correctly align individual screenshots after adding them through CopyFromScreen.

So we have this solution:

 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 } } 

Or install it through NuGet ( disclaimer: I am the author ):

 PM> Install-Package Pranas.ScreenshotCapture 

We use it in our product on many settings, so we periodically improve the code and put notes on the blog .

+2
source

With Mono 2.4.4 you can get the whole screen without 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
source

Source: https://habr.com/ru/post/1308117/


All Articles