Wednesday, May 29, 2013

Transmitting Intervaled Screen Captures

This article shows how  to periodically capture the entire desktop and store it to files and optionally transmit the captured files on the Internet. The code is in C# and so the program only supports operating systems where C# desktop apps could run: mainly Windows-based systems.

I've chosen a hidden Windows app as my main driver. You could have very well chosen a console or a service process as your main driver. The app is hidden from ordinary users (of course there are ways to detect that the app is running in the background).

The app starts a timer and on timed-interval checks for the existence of a resource or an event to determine whether it should gracefully terminate or do another screen capture. The external resource in our case is a text file that the administrator could dump into a known or configured folder. The existence of the file signals to the app that it ought to terminate;  otherwise the app captures the entire desktop and dumps it to a file in the configured folder.

The "timer repetition interval", "folder name", "capture base file name", "termination file name",  "maximum number of files to write" are configured in app.config.

The capture file name is computed as: configured capture base file name + Counter + .extension.
Above the Counter is an integer that is incremented in our app. When the Counter reaches "maximum number of files to write" the Counter is reset to 0 and we would override the previously written files.

On my next article I will touch upon transmitting the captured files to the Internet. From that point possibilities are only limited by our imagination: the app could be used as a monitoring tool, replace rudimentary video conferencing tools, etc.

The C# code is listed below:

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

namespace WindowsFormsApplication1
{
    static class Program
    {
        ///



        /// The main entry point for the application.
        ///
        [STAThread]
        static void Main()
        {
              Timer MyTimer = new Timer();
              //  mins converted to milliseconds
              MyTimer.Interval = (Convert.ToInt32(ConfigurationManager.AppSettings["CaptureMinutesInterval"]) * 60 * 1000);
                MyTimer.Tick += new EventHandler(Timer_Tick);
                MyTimer.Start();
                Application.Run();

        }
        static int counter = 0;
        private static void Timer_Tick(object sender, EventArgs e)
        {
            if (File.Exists(ConfigurationManager.AppSettings["FilePath"] + ConfigurationManager.AppSettings["EndFile"]))
            {
                Application.Exit();
                return;
            }


            if (!System.IO.Directory.Exists(ConfigurationManager.AppSettings["FilePath"]))
            {
                System.IO.Directory.CreateDirectory(ConfigurationManager.AppSettings["FilePath"]);
            }

         
            int screenWidth = Screen.GetBounds(new Point(0, 0)).Width;
            int screenHeight = Screen.GetBounds(new Point(0, 0)).Height;

            // Rectangle bounds = Screen.GetBounds(Point.Empty);
            using (Bitmap bitmap = new Bitmap(screenWidth, screenHeight))
            {
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.CopyFromScreen(0, 0, 0, 0, new Size(screenWidth, screenHeight));
                }
                // could use other extensions
                bitmap.Save(ConfigurationManager.AppSettings["FilePath"] + ConfigurationManager.AppSettings["CapBaseName"] + counter +
                    ".png", ImageFormat.Png);
                counter++;
                if (Convert.ToInt32(ConfigurationManager.AppSettings["MaxFiles"]) > counter)
                {
                    counter = 0;
                }
            }
        }
    }
}