The answer is simple if you are using Firefox with the Firebug add-on or Internet Explorer 8: Use the console.log mechanism and write your debug output to the Browser’s debug console.
Here's a simple extension method, which logs an object to the console.log:
public static void Log(this object obj) { HtmlWindow window = HtmlPage.Window; var isConsoleAvailable = (bool)window.Eval("typeof(console) != 'undefined' && typeof(console.log) != 'undefined'"); if (isConsoleAvailable) { var console = (window.Eval("console.log") as ScriptObject); if (console != null) { console.InvokeSelf(obj); } } }
How to you use it:
"Hello Universe!".Log(); int a = 42; a.Log(); String.Format("The answer to all questions is {0}.", a).Log();
And that's how the debug output looks within Firebug:
Nice tip! I might just use this. Thanks.
ReplyDeleteThanks for this tip! It really helped me out.
ReplyDeleteI modified the code slightly to check for the existence of console and console.log. That way it will quietly fail (i.e., it won't throw an InvalidOperationException on Eval) if it's running in IE8 with the "Developer Tools" window closed or in earlier versions of IE.
HtmlWindow window = HtmlPage.Window;
object hasConsole = window.Eval("typeof(console) != 'undefined' && typeof(console.log) != 'undefined'");
if (hasConsole is bool && (bool)hasConsole)
{
ScriptObject consoleLogFunction = window.Eval("console.log") as ScriptObject;
if (consoleLogFunction != null)
{
consoleLogFunction.InvokeSelf(entry);
}
}
@Bill I totally missed that. Thanks for your comment! I updated the code snippet.
ReplyDeleteWhere can you get System.Windows.Forms for silverlight?
ReplyDeleteHtmlPage.Window fails in none UI thread, so I call the above code from System.Windows.Deployment.Current.Dispatcher.BeginInvoke().
ReplyDeleteIt also works for Google Chrome if you install FireBug lite for chrome.
ReplyDeleteIt fails unless you call the Log method form the UI thread. Any idea on how to retrieve the Dispatcher of the current Visual element?
ReplyDeleteHi Jarana,
ReplyDeletesure, it's the Application.Current.RootVisual.Dispatcher
Use it like this:
Application.Current.RootVisual.Dispatcher.BeginInvoke(() => "Log from another thread in the UI thread!".Log());
This comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThanks a lot, that's a great info.
ReplyDeleteJust to note that in case you are using Google Chrome without FireBug lite for chrome (which I just installed) the code is likely to crash during the consoleLogFunction.InvokeSelf, due to a System.InvalidOperationException exception.
You could do the Try/Catch trick to surround the call, unless there is a better test you could perform instead.
Vincent Thavonekham.
I just wanted to share my workaround for the Chrome exception when Invoking console.log.
ReplyDeleteMy solution creates a user defined javascript function containing the call to console.log and passing the message as a parameter. I then call eval.call (window.execScript in IE) to load the function into global scope and then I can invoke my custom function instead of console.log directly. This works perfectly in Chrome.
public void Log(LogLevel loglevel, string message)
{
if (loglevel <= level)
{
HtmlWindow window = HtmlPage.Window;
//only log if a console is available
var isConsoleAvailable = (bool)window.Eval("typeof(console) != 'undefined' && typeof(console.log) != 'undefined'");
if (isConsoleAvailable)
{
var createLogFunction = (bool)window.Eval("typeof(ssplog) == 'undefined'");
if (createLogFunction)
{
// Load the logging function into global scope:
string logFunction = @"function ssplog(msg) { console.log(msg); }";
string code = string.Format(@"if(window.execScript) {{ window.execScript('{0}'); }} else {{ eval.call(null, '{0}'); }}", logFunction);
window.Eval(code);
}
// Prepare the message
DateTime dateTime = DateTime.Now;
string output = string.Format("{0} - {1} - {2}", dateTime.ToString("u"), loglevel.ToString(), message);
// Invoke the logging function:
var logger = window.Eval("ssplog") as ScriptObject;
logger.InvokeSelf(output);
}
}
}
Thanks for this, it worked for chrome and IE
DeleteWhat is it LogLevel ?
DeleteIMHO, I prefer if (!isConsoleAvailable) return;
Really nice stuff. I am trying to use your logger but it's working on IE9 but not on Chrome... By any chance, do you have a workaround to make it work on Chrome too? or at least make it fail silently on Chrome?
ReplyDeleteThanks a lot,
Albino
works great! thanks! I tested in IE and Chrome both worked fine!
ReplyDelete