 |
|
 |
// This delegate enables asynchronous calls for setting // the text property on a TextBox control. delegate void OutputViewAddCallback(ListViewItem Elem);
private void OutputViewAdd(ListViewItem Elem) { // InvokeRequired required compares the thread ID of the // calling thread to the thread ID of the creating thread. // If these threads are different, it returns true. if (this.OutputView.InvokeRequired) { OutputViewAddCallback d = new OutputViewAddCallback(OutputViewAdd); this.Invoke(d, new object[] { Elem }); } else { if(Elem.Text.Length>0) this.OutputView.Items.Add(Elem ); else this.OutputView.EnsureVisible(this.OutputView.Items.Count - 1); } }
public ListViewItem CreateEventRow() { DateTime d=DateTime.Now;
// create a ListView item/subitems : [event nb] - [time] - [empty string] string msg1 = (++EventCounter).ToString(); string msg2 = d.ToLongTimeString(); ListViewItem elem = new ListViewItem(msg1); elem.SubItems.Add(msg2); elem.SubItems.Add(""); //OutputViewAdd(elem ); //this.OutputView.Items.Add(elem);
// we save the message item for incoming text updates CurrentMsgItem=elem.SubItems[2]; CurrentMsgItem.Tag = elem; return elem; }
public void UpdateCurrentRow(bool CreateRowNextTime) { ListViewItem elem; if (CurrentMsgItem==null) CreateEventRow(); elem = (ListViewItem )CurrentMsgItem.Tag;
CurrentMsgItem.Text=Buffer.ToString(); OutputViewAdd(elem );
// if null, a new row will be created next time this function is called if (CreateRowNextTime==true) CurrentMsgItem=null;
// this is the autoscroll, move to the last element available in the ListView if (this.CheckScroll.CheckState == CheckState.Checked) { OutputViewAdd(new ListViewItem("")); //this.OutputView.EnsureVisible(this.OutputView.Items.Count-1); } }
Henry
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
It does not seem to work for VS 2005 and don't know if this work for .net framework 2.0, so I going to attempt to write my version of this debug console. I'm going to use singleton approach, because I just pick it up from Head First Desig n Pattern.
I welcome comment and tips associated with this subject. Is there way of fixing thread safe issue? Once done, I hope to release it to community via CodeProject webpage.
I also considering adding text colour as well, so that it get attention if there is bad data or need alerting.
>It's not so much what you have to learn if you accept weird theories, it's what you have to unlearn. (Isaac Asimov) >Life's journey is not to arrive at the grave safely in a well preserved body,but rather to skid in sideways, totally worn out, shouting "...holy sh*t...what a ride! [Riscy]
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
Hi, I wait for a week and if I hear nothing from author, I try release it on CodeProject.
>It's not so much what you have to learn if you accept weird theories, it's what you have to unlearn. (Isaac Asimov) >Life's journey is not to arrive at the grave safely in a well preserved body,but rather to skid in sideways, totally worn out, shouting "...holy sh*t...what a ride! [Riscy]
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
I noticed that you said you incorporated changes several times throughout the posts; however, it looks like you never updated the source files here. Is there any way you can upload the latests files?
Thanks
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I run a Virtual PC to test my C#, and it naturally does not have the Visual Studio debugger. This has saved me hours.
To reiterate what another user mentioned, having a UI thread to ensure updates are done asynchronously would be ideal.
Thanks, Brad
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
nice work for multithreaded programs debug messages might be launched by off-ui-threads as well, but only the ui thread is allowed to change the interface objects directly according to ms tech docs so you should check for InvokeRequired in your UpdateCurrentRow and reestabslish a ui thread safe call call via Invoke( new UpdateCurrentRowDelegate( UpdateCurrentRow ), new object [] { CreateRowNextTime ) )
greetz steve
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Thanks, it saves me cluttering my console output. I made one small change, as I am running a few apps at the same time, I added a Caption functionality, to make it easier to know which DebugConsole belongs to which App. I overloaded the Init method with the following:
public void Init(bool UseDebugOutput, bool UseCrForWriteLine, string Caption){
DebugForm.Text=Caption;
Init (UseDebugOutput, UseCrForWriteLine);
}
Being in a minority of one, doesn't make you insane George Orwell However, in my case it does
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi there, Great work, I'm just playing with it at the moment.
The method you use to create a singleton seems like a pretty elegant one line solution - do you know if it's thread safe? I wrote an article for Singletons using C++, and am still no way near as proficient in C# - but using a static variable like this would cause thread safety issues in C++.
If I make any changes that take this into account (if it matters) I'll give you the source with changes.
Also I noticed that you plonked the DebugConsole class in the System.Diagnostics namespace. I think you should reconsider using your own namespace just incase MS decide to extend the language and put their own DebugConsole class in the System.Diagnostics namespace.
Cheers,
Paul
/********************************** Paul Evans, Dorset, UK. Personal Homepage "EnjoySoftware" @ http://www.enjoysoftware.co.uk/ **********************************/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I couldn't see a way of e-mailing you, so here's some changes I made, incase u are interested.
Thanks for this great starting point!
Paul
#define TRACE
#if (!(TRACELISTENER)) #define TRACELISTENER #endif
namespace PDE.Debug { using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.IO; using System.Text; using System.Diagnostics;
sealed class DebugConsole : TraceListener { public static readonly DebugConsole Instance = new DebugConsole();
private DebugConsoleWrapper DebugForm = new DebugConsoleWrapper(); private bool UseCrWl = true; private bool m_bInit = false;
private DebugConsole() { }
public void Init(bool UseDebugOutput, bool UseCrForWriteLine) { if (UseDebugOutput==true) Debug.Listeners.Add(this); else Trace.Listeners.Add(this);
this.UseCrWl = UseCrForWriteLine; DebugForm.Show(); this.m_bInit=true; Trace.WriteLine("--- DEBUG CONSOLE LOG INITIALISED ---"); } public void Init(bool UseDebugOutput) { Init(UseDebugOutput, true); } public void Init() { #if (DEBUG) Init(true,true); Trace.WriteLine("--- (Initialised using defaults (Debug mode, writing new lines) ---"); #else Init(false,true); Trace.WriteLine("--- (Initialised using defaults (Trace mode, writing new lines) ---"); #endif }
override public void Write(string message) { if (!m_bInit) { Init(); } DebugForm.Buffer.Append(message); DebugForm.UpdateCurrentRow(false); }
override public void WriteLine(string message) { if (!m_bInit) { Init(); }
if (this.UseCrWl==true) { DebugForm.CreateEventRow(); DebugForm.Buffer=new StringBuilder(); }
DebugForm.Buffer.Append(message); DebugForm.UpdateCurrentRow(true); DebugForm.Buffer.Length = 0; } private class DebugConsoleWrapper : System.Windows.Forms.Form { private System.Windows.Forms.Button BtnSave; private System.Windows.Forms.Button BtnClear; private System.Windows.Forms.SaveFileDialog SaveFileDlg; private System.Windows.Forms.CheckBox CheckScroll; private System.Diagnostics.DefaultTraceListener Tracer = new System.Diagnostics.DefaultTraceListener(); private System.Windows.Forms.ColumnHeader Col1; private System.Windows.Forms.ColumnHeader Col2; private System.Windows.Forms.ListView OutputView; private System.Windows.Forms.CheckBox CheckTop; private System.Windows.Forms.Panel panel2; private System.Windows.Forms.ColumnHeader Col3; private ListViewItem.ListViewSubItem CurrentMsgItem = null; private int EventCounter=0; public StringBuilder Buffer = new StringBuilder(); private System.ComponentModel.Container components = null; public DebugConsoleWrapper() { InitializeComponent(); } protected override void Dispose( bool disposing ) { if( disposing ) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code private void InitializeComponent() { this.BtnSave = new System.Windows.Forms.Button(); this.BtnClear = new System.Windows.Forms.Button(); this.SaveFileDlg = new System.Windows.Forms.SaveFileDialog(); this.CheckScroll = new System.Windows.Forms.CheckBox(); this.OutputView = new System.Windows.Forms.ListView(); this.Col1 = new System.Windows.Forms.ColumnHeader(); this.Col2 = new System.Windows.Forms.ColumnHeader(); this.Col3 = new System.Windows.Forms.ColumnHeader(); this.CheckTop = new System.Windows.Forms.CheckBox(); this.panel2 = new System.Windows.Forms.Panel(); this.panel2.SuspendLayout(); this.SuspendLayout(); this.BtnSave.Location = new System.Drawing.Point(8, 16); this.BtnSave.Name = "BtnSave"; this.BtnSave.Size = new System.Drawing.Size(64, 24); this.BtnSave.TabIndex = 8; this.BtnSave.Text = "Save"; this.BtnSave.Click += new System.EventHandler(this.BtnSave_Click); this.BtnClear.Location = new System.Drawing.Point(80, 16); this.BtnClear.Name = "BtnClear"; this.BtnClear.Size = new System.Drawing.Size(64, 24); this.BtnClear.TabIndex = 8; this.BtnClear.Text = "Clear"; this.BtnClear.Click += new System.EventHandler(this.BtnClear_Click); this.CheckScroll.Checked = true; this.CheckScroll.CheckState = System.Windows.Forms.CheckState.Checked; this.CheckScroll.Location = new System.Drawing.Point(152, 16); this.CheckScroll.Name = "CheckScroll"; this.CheckScroll.Size = new System.Drawing.Size(80, 16); this.CheckScroll.TabIndex = 8; this.CheckScroll.Text = "autoscroll"; this.CheckScroll.CheckedChanged += new System.EventHandler(this.CheckScroll_CheckedChanged); this.OutputView.AutoArrange = false; this.OutputView.BackColor = System.Drawing.Color.MediumAquamarine; this.OutputView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.Col1, this.Col2, this.Col3}); this.OutputView.Dock = System.Windows.Forms.DockStyle.Fill; this.OutputView.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0))); this.OutputView.ForeColor = System.Drawing.Color.Black; this.OutputView.Name = "OutputView"; this.OutputView.Size = new System.Drawing.Size(400, 200); this.OutputView.TabIndex = 7; this.OutputView.View = System.Windows.Forms.View.Details; this.Col1.Text = "#"; this.Col1.Width = 40; this.Col2.Text = "Time"; this.Col2.Width = 100; this.Col3.Text = "Message"; this.Col3.Width = 400; this.CheckTop.Location = new System.Drawing.Point(240, 16); this.CheckTop.Name = "CheckTop"; this.CheckTop.Size = new System.Drawing.Size(96, 16); this.CheckTop.TabIndex = 8; this.CheckTop.Text = "always on top"; this.CheckTop.CheckedChanged += new System.EventHandler(this.CheckTop_CheckedChanged); this.panel2.Controls.AddRange(new System.Windows.Forms.Control[] { this.BtnSave, this.BtnClear, this.CheckScroll, this.CheckTop}); this.panel2.Dock = System.Windows.Forms.DockStyle.Bottom; this.panel2.Location = new System.Drawing.Point(0, 200); this.panel2.Name = "panel2"; this.panel2.Size = new System.Drawing.Size(400, 48); this.panel2.TabIndex = 8; this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(400, 248); this.Controls.AddRange(new System.Windows.Forms.Control[] { this.OutputView, this.panel2}); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; this.MinimumSize = new System.Drawing.Size(450, 160); this.Name = "DebugConsoleWrapper"; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; this.Text = "Debug Console"; this.panel2.ResumeLayout(false); this.ResumeLayout(false); } #endregion public void CreateEventRow() { DateTime d=DateTime.Now; string msg1 = (++EventCounter).ToString(); string msg2 = d.ToLongTimeString(); ListViewItem elem = new ListViewItem(msg1); elem.SubItems.Add(msg2); elem.SubItems.Add(""); this.OutputView.Items.Add(elem); CurrentMsgItem=elem.SubItems[2]; } public void UpdateCurrentRow(bool CreateRowNextTime) { if (CurrentMsgItem==null) CreateEventRow(); CurrentMsgItem.Text=Buffer.ToString(); if (CreateRowNextTime==true) CurrentMsgItem=null; if (this.CheckScroll.CheckState == CheckState.Checked) { this.OutputView.EnsureVisible(this.OutputView.Items.Count-1); } } private void BtnSave_Click(object sender, System.EventArgs e) { this.SaveFileDlg.Filter="Text file (*.txt)|*.txt|All files (*.*)|*.*" ; this.SaveFileDlg.FileName="log.txt"; this.SaveFileDlg.ShowDialog(); FileInfo fileInfo = new FileInfo(SaveFileDlg.FileName); StreamWriter s = fileInfo.CreateText(); for (int i=0;i { StringBuilder sb=new StringBuilder(); sb.Append(this.OutputView.Items[i].SubItems[0].Text); sb.Append("\t"); sb.Append(this.OutputView.Items[i].SubItems[1].Text); sb.Append("\t"); sb.Append(this.OutputView.Items[i].SubItems[2].Text); s.WriteLine(sb.ToString()); } s.Close(); } private void BtnClear_Click(object sender, System.EventArgs e) { this.EventCounter=0; this.CurrentMsgItem=null; this.OutputView.Items.Clear(); this.Buffer.Length = 0; } private void CheckTop_CheckedChanged(object sender, System.EventArgs e) { if (this.CheckTop.CheckState == CheckState.Checked) this.TopMost = true; else this.TopMost = false; } private void CheckScroll_CheckedChanged(object sender, System.EventArgs e) { if (this.CheckScroll.CheckState == CheckState.Checked) this.OutputView.EnsureVisible(this.OutputView.Items.Count-1); } } } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Why use a separate interface to log events to your debug window? Just have the DebugConsole class inherit from System.Diagnostics.TraceListener, add it to the Listeners collection for the Debug and Trace objects, and use the standard Debug.WriteLine, etc.:
using System.Diagnostics; using System.Text; ... sealed class DebugConsole : TraceListener { private static readonly DebugConsole Instance;
static DebugConsole() { Instance = new DebugConsole(); Trace.Listeners.Add(Instance); Debug.Listeners.Add(Instance); }
private DebugConsoleWrapper DebugForm = new DebugConsoleWrapper(); private StringBuilder Buffer = new StringBuilder();
private DebugConsole() { DebugForm.Show(); }
public void Write(string message) { Buffer.Append(message); }
public void WriteLine(string message) { if (Buffer.Length == 0) DebugForm.WriteLine(message); else { Buffer.Append(message); DebugForm.WriteLine(Buffer.ToString()); Buffer = new StringBuilder(); } }
}
Form1 would then become:
using System; ... using System.Diagnostics;
namespace DebugConsoleSample { public class Form1 : System.Windows.Forms.Form { ...
[STAThread] static void Main() { Debug.WriteLine("Function call : Application.Run(new Form1())"); Application.Run(new Form1()); }
private void textBox1_TextChanged(object sender, System.EventArgs e) { Debug.WriteLine("Event : textBox1_TextChanged "); }
private void button1_Click(object sender, System.EventArgs e) { Debug.WriteLine("Event : button1_Click - textBox1 string : " + textBox1.Text.ToString());
Debug.WriteLine("Start a loop...");
for (int i=0;i<5;i++) Debug.WriteLine("Loop counter : " + i.ToString()); }
private void trackBar1_Scroll(object sender, System.EventArgs e) { Debug.WriteLine("Event : trackBar1_Scroll : " + trackBar1.Value.ToString()); } } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
 |
That right there is the best utility ever invented for debuggin'. Praise sysinternals. They have saved my butt more times than i care to count.
Joseph Dempsey jdempsey@cox.rr.com Joseph.Dempsey@thermobio.com "Software Engineering is a race between the programmers, trying to make bigger and better fool-proof software, and the universe trying to make bigger fools. So far the Universe in winning." --anonymous
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I didn't know this good looking util Have to try it and maybe this will be the source of inspiration for future versions
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Why use OutputDebugString when the System.Diagnostics has the Trace & Debug classes with tons of static methods (including WriteLineIf and Assert for optional output) which means it requires even less work (no interop)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
yep, that's what the new version of my console is using. I have to look at the other methods of these classes and override them.
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |