Forum Moderators: open

Message Too Old, No Replies

screen capture

view visitor's screen to see error message

         

bwstyle

3:45 pm on Nov 3, 2006 (gmt 0)

10+ Year Member



When we get a call saying "your site is broken", or "I get an error" from a user with no other information, it becomes frustrating.

It would be nice if we could be at their computer to see what they're seeing & get the information we need to troubleshoot. Or can we?

Is there a way to capture a screen or browser content and then send it back to us? My first guess would be javascript.

pmkpmk

3:50 pm on Nov 3, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



That would be quite a severe security breach, wouldn't it?

Try remote servicing solutions like LogMeIn and GotoMeeting or a VNC setup.

Fotiman

3:56 pm on Nov 3, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



You could tell the user to just take a screen capture:

1. Select the browser window
2. Press ALT+Print Screen
3. Create a new email message using email program and paste in the screen shot from the clipboard using CTRL+V

This obviously won't work if they're using some form of Web Mail application instead of Outlook.

john_k

4:05 pm on Nov 3, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Here is some code I used on a project a few years ago. It was an intranet site, so all users were using IE. (that means I don't know how it will work on other browsers). Hopefully it will get you close to what you need.


<!--
window.onerror=handleJsError; //set callback function, called by javascript when an error occurs
var jsErrArray=new Array(); //stores javascript error information, can hold multiple errors
var jsFunStack=new Array(); //stores names of functions in play when an error occurs
var relpath=''; //relative location from site root, is further initialized by hosting page
/*
handleJsError:
This function is established (above) as the function to be called by javascript whenever
a javascript error occurs. The function puts the error information into the jsErrArray,
it puts the current function stack into the jsFunStack array, and then it asks the
user if they want to send an error report. If they elect to do so, then it calls the
sendError function to handle those details.
*/
function handleJsError(msg, url, lno)
{
//store the error message, url, and line-number
jsErrArray[jsErrArray.length]='Error Desc: '+msg+'\nLine Nr: '+lno+'\nFile: '+url;
//capture and store the current function stack
jsFunStack[jsFunStack.length]=stacktrace();
//Enable this line for debugging purposes
//alert('JAVASCRIPT ERROR DETAILS\nLINE: '+lno+'\nFILE: '+url+'\nMESSAGE: '+msg);
//ask the user if they want to send an error report
if(confirm('A JavaScript error has occurred: '+msg+'\n\nClick the \'OK\' button to send an error report to system support.'))
sendError(relpath);
return true;
}
/*
sendError:
This function grabs the html residing between the body and /body tags. Since it gets it
from the DOM model, it represents the current state of the page. i.e. It will capture
any text that has been typed into text or textarea fields, any selections in list boxes,
checkbox state, etc.
It then submits the html along with other page particulars to the website.
*/
function sendError(pathOffset)
{
var oFrm; //the form we will create and then use to submit the error information.
//get a copy of the current HTML, before we disable the links (limitation: this only gets
//what is between the body and /body tags). This copy of the HTML is for the support
//person to look at.
var bodyTextOriginal=document.body.innerHTML;
//disable all links in the HTML. This needs to be done to avoid all kinds of odd-ball
//errors that could occur when we later try to display this HTML in our error report page.
disableLinks();
//get a copy of the HTML with the links disabled. This copy of the HTML is used to render
//a screen shot of the errant page.
var bodyTextA=document.body.innerHTML;
//Adjust paths on src attributes so that images will display okay in the error report page
if(pathOffset!='')
var re=new RegExp("src=\""+pathOffset,"gi")
else
var re=new RegExp("src=\"","gi");
var bodyText=bodyTextA.replace(re,'src="../');
//attempt to get a reference to the frmSendError form. This would normally return null, but
//it is possible that it already exists if this is our second pass through this function.
oFrm=document.getElementById('frmSendError');
//if we didn't find and instance of the frmSendError form, then create it
if(!oFrm)
{
oFrm = document.createElement('<form name="frmSendError" method="post" action="'+pathOffset+'Help/ErrorReport.asp">');
document.appendChild(oFrm);
}
//---begin populating the form fields
//capture page href
var oField = document.createElement("<textarea name='pagehref'>");
oField.value = document.location.href;
oFrm.appendChild(oField);
//capture page title
var oField = document.createElement("<textarea name='pagetitle'>");
oField.value = document.title;
oFrm.appendChild(oField);
//capture page html (with links deactivated)
var oField = document.createElement("<textarea name='pagebodyA'>");
oField.value=bodyText;
oFrm.appendChild(oField);
//capture page original html
var oField = document.createElement("<textarea name='pagebodyB'>");
oField.value=bodyTextOriginal;
oFrm.appendChild(oField);
//capture javascript errors from the jsErrArray
var oField = document.createElement("<textarea name='javascripterrors'>");
if(jsErrArray.length>0)
oField.value=jsErrArray.join('\n\n')
else
oField.value='';
oFrm.appendChild(oField);
//capture javascript error function stack(s) from the jsFunStack array
var oField = document.createElement("<textarea name='javascriptfunstack'>");
if(jsFunStack.length>0)
oField.value=jsFunStack.join('\n\n')
else
oField.value='';
oFrm.appendChild(oField);
//---end populating the form fields
//send the form
oFrm.submit();
return true;
}
/*
disableLinks:
This function will disable all links in the document.
*/
function disableLinks()
{
var oLink;
if(document.links.length>0)
{
for(var i=0;i<document.links.length;i++)
{
document.links[i].href='#';
document.links[i].onclick='alert(\'Links, buttons, and menus are disabled in the screenshot.\');return false;';
document.links[i].target='';
}
}
}
/*
funcname:
This function returns the name of a given function. It does this by
converting the function to a string, then using a regular expression
to extract the function name from the resulting code.
*/
function funcname(f) {
var s = f.toString().match(/function (\w*)/)[1];
if(s == 'anonymous')
{
var l=f.toString().substr(23,60).split(' ');
if(l.length>0)
return l[1];
}
if ((s == null) ¦¦ (s.length == 0)) return "anonymous";
return s;
}
/*
stacktrace:
This function returns a string that contains a "stack trace."
*/
function stacktrace() {
var s = ""; // This is the string we'll return.
var fName = ""; // The name of a function
// Loop through the stack of functions, using the caller property of
// one argument's object to refer to the next argument's object on the
// stack.
for(var a = arguments.caller; a!= null; a = a.caller) {
// Add the name of the current function to the return value. (But
// don't add the error handler function)
fName = funcname(a.callee);
if(fName!='handleJsError')
s+=fName+"\n";
// Because of a bug in Navigator 4.0, we need this line to break.
// a.caller will equal a rather than null when we reach the end
// of the stack. The following line works around this.
if (a.caller == a) break;
}
return s;
}
//-->

RonPK

4:54 pm on Nov 3, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



That's a nice piece of code, john_k. Thanks for sharing it!

bwstyle

9:55 pm on Nov 3, 2006 (gmt 0)

10+ Year Member



wow very helpful. it has me thinking...

We can use PHP.

What if I started each page out with
ob_start();
$error=false;

Then check for errors that may happen and set $error=true; when they do.

Script and code the page normally. In the end:

if($error)
mail('tech@team.com', 'error report', ob_get_contents());

ob_end_flush();

We've now sent the HTML as the user sees it! I think this works but I wanted to share and see what everyone thinks.

whoisgregg

11:51 pm on Nov 3, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



That will work bwstyle. :)

I'd also include the $_POST and $_GET superglobals in the email.

Added: And $_COOKIE too. With all that information you'll know precisely what the user provided and what they received. :)

pmkpmk

12:59 pm on Nov 4, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Scary.

whoisgregg

7:33 pm on Nov 6, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Scary.

I suppose a discussion of privacy concerns would warrant it's own thread. (Although in this case, we're only discussing logging of dynamic page requests on our own sites so I fail to see any concern.)