Derik Whittaker

Syndication

News


Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
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');

Posted 11-01-2006 7:04 AM by Derik Whittaker
Filed under: , ,

[Advertisement]

Comments

Bob Yexley wrote re: Using a Screen Shot to help Trouble Shoot your deployed application
on 11-01-2006 9:46 AM

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.

Martin Knotek wrote re: Using a Screen Shot to help Trouble Shoot your deployed application
on 11-02-2006 1:47 AM

Nice

Sumusu wrote re: Using a Screen Shot to help Trouble Shoot your deployed application
on 12-14-2006 11:18 PM

i need some code sir

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)