1

I'm using the below code to capture snapshots of desktop.

    using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.IO;

namespace SMSServer
{
    class CaptureDesktop
    {
        // P/Invoke declarations
        [DllImport("gdi32.dll")]
        static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int
        wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, CopyPixelOperation rop);
        [DllImport("user32.dll")]
        static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc);
        [DllImport("gdi32.dll")]
        static extern IntPtr DeleteDC(IntPtr hDc);
        [DllImport("gdi32.dll")]
        static extern IntPtr DeleteObject(IntPtr hDc);
        [DllImport("gdi32.dll")]
        static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
        [DllImport("gdi32.dll")]
        static extern IntPtr CreateCompatibleDC(IntPtr hdc);
        [DllImport("gdi32.dll")]
        static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
        [DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr ptr);

        private static string filePath = Directory.GetCurrentDirectory() + @"\CurrentImage.png";
        public void CaptureDesktopAsImage()
        {
            Size sz = Screen.PrimaryScreen.Bounds.Size;
            IntPtr hDesk = GetDesktopWindow();
            IntPtr hSrce = GetWindowDC(hDesk);
            IntPtr hDest = CreateCompatibleDC(hSrce);
            IntPtr hBmp = CreateCompatibleBitmap(hSrce, sz.Width, sz.Height);
            IntPtr hOldBmp = SelectObject(hDest, hBmp);
            bool b = BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, 0, 0,         CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
            Bitmap bmp = Bitmap.FromHbitmap(hBmp);
            SelectObject(hDest, hOldBmp);
            DeleteObject(hBmp);
            DeleteDC(hDest);
            ReleaseDC(hDesk, hSrce);
            bmp.Save(filePath);
            bmp.Dispose();            
        }
    }
}

Everything is working fine, but memory consumption is too high. Increasing rapidly. Upon profiling the app with JetBrains dotMemory, I found that it is due to the above code. I also see that before method ends, a call to Dispose() is made to remove allocations. Still memory consumption is high.

How can I improve the above code to fix memory leaks? Any Ideas?

kunaguvarun
  • 703
  • 1
  • 10
  • 29
  • 2
    I can't reproduce this on my Win 7 desktop. If I make rapid captures of my desktop (2560x1600) in a small test app, the reported managed memory bounces around between 1.5 and 5 MB. If I add a call to `GC.Collect()` it stays stable around 1.7 MB. Total memory as reported by Task Manager Commit Size, and number of GDI objects in use, also stay stable. – dbc Jan 05 '15 at 06:26
  • 1
    Is there any chance that an exception is thrown partway through, thereby skipping freeing memory? – dbc Jan 05 '15 at 06:39
  • Forgot to mention that I make calls to CaptureDesktopAsImage() method, as written in the Server section of this question: http://stackoverflow.com/questions/27756389/c-sharp-stream-desktop-activity. No exception is thrown as far as I tested – kunaguvarun Jan 05 '15 at 09:07
  • Where should I place the call to GC.Collect()? In the calling method or the called method? – kunaguvarun Jan 05 '15 at 09:08

1 Answers1

0

Try the below solutions, may be it helps Assign null for your unmanged object and then dispose it..

Use the below Cleanup code

GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(<your Unmanaged Object>);

If any object has close() and open() methods, then mention close() before Releasing the Com object..

Hope this helps.

Bhuvan Ram
  • 61
  • 3