Devlico.Us
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @devlicious

Derik Whittaker

Thoughts on Software Development, .Net, OOP, Design Patterns and all things cool



Using a Screen Shot to help Trouble Shoot your deployed application

On my current project I wanted a way to help maintain our application after deployment.  Sure I have added logging, I have added the ability to email the stack trace to an email account, but neither of these will tell me exactly what the user was actually doing at the time of the exception.  And my experience has taught me that if you ask the user what to explain to exactly what they were doing they will either a) not remember or b) not give you ALL the details you need.

So in order to help me with this I decided to implement the ability to take a screen shot of the application when an exception occurs.  Setting this up was actually pretty easy.  Below are the steps needed to implement this in your application.

Steps
  1. Creating the screen shot library
  2. Setting up the application to  globally listen for unhandeled exceptions
  3. Taking the screen shot and saving it to disk.


1) Creating the screen shot library
*** NOTE *** I know there are many ways to take a screen shot in .net, this is just one way

Importing methods from gdi32.dll: 

        [DllImportAttribute( "gdi32.dll" )]

        private static extern IntPtr CreateDC(

              string lpszDriver,        // driver name

              string lpszDevice,        // device name

              string lpszOutput,        // not used; should be NULL

            IntPtr lpInitData    // optional printer data

                  );

 

        [DllImportAttribute( "gdi32.dll" )]

        private static extern bool BitBlt(

            IntPtr hdcDest, // handle to destination DC

            int nXDest,  // x-coord of destination upper-left corner

            int nYDest,  // y-coord of destination upper-left corner

            int nWidth,  // width of destination rectangle

            int nHeight, // height of destination rectangle

            IntPtr hdcSrc,  // handle to source DC

            int nXSrc,   // x-coordinate of source upper-left corner

            int nYSrc,   // y-coordinate of source upper-left corner

            Int32 dwRop  // raster operation code

 

Taking the screen shot: 

 

        public static Image ScreenShotAsJPG()

        {

            IntPtr dc1 = CreateDC( "DISPLAY", null, null, ( IntPtr ) null );

            Graphics g1 = Graphics.FromHdc( dc1 );

 

            Image MyImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, g1);

 

            Graphics g2 = Graphics.FromImage( MyImage );

 

            dc1 = g1.GetHdc();

            IntPtr dc2 = g2.GetHdc();

 

            BitBlt( dc2, 0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, dc1, 0, 0, 13369376 );

 

            g1.ReleaseHdc( dc1 );

            g2.ReleaseHdc( dc2 );

 

            return MyImage;

        }

 

Saving the screen shot to disk: 

 

        public static string SaveScreenShot( Image image)

        {

            string outputFolder = GetApplicationPath( );

            string screenshotFilePath = CreateSaveFileName( outputFolder, 0 );

 

            if ( !Directory.Exists( outputFolder ))

            {

                Directory.CreateDirectory( outputFolder );

            }

 

            image.Save( screenshotFilePath, ImageFormat.Jpeg );

 

            CleanupScreenshots( );

 

            return screenshotFilePath;

        }

 

Wiring up your application to handle Unhandled Exceptions:

This needs to be done in your main startup routine (it is assume that you are using a main() method as your startup)

 

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler( CurrentDomain_UnhandledException );

 

The code to take the screen shot

 

        private static void CurrentDomain_UnhandledException( object sender, UnhandledExceptionEventArgs e )

        {

            ScreenCapture.SaveScreenShot( ScreenCapture.ScreenShotAsJPG() );

 

            // Perform any other logging/clean up needed

        }

 

Well there you have it, a simple way to take a screen shot of your application when an exception occurs.

 

Let me your thoughts, is there a different/better way? 

dp.SyntaxHighlighter.HighlightAll('code');


Comments

Bob Yexley said:

Very cool idea. Thanks for sharing. I wish I had known about this last year...would've been really helpful on the project I was on then, heh. Oh well, I'm sure it'll be helpful in the future too.

# November 1, 2006 9:46 AM

Martin Knotek said:

Nice

# November 2, 2006 1:47 AM

Sumusu said:

i need some code sir

# December 14, 2006 11:18 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Derik Whittaker

Derik is a .Net Developer/Architect specializing in WinForms working out the northern suburbs of Chicago. He is also believer and advocate for Agile development including SCRUM, TDD, CI, etc.

When Derik is not writing code he can be found spending time with his wife and young son, climbing on his bouldering wall, watching sports (mostly baseball), and generally vegging out. Check out Devlicio.us!

Our Sponsors

Proudly Partnered With


This Blog

Syndication

News