]>
git.saurik.com Git - wxWidgets.git/blob - samples/debugrpt/debugrpt.cpp
1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: minimal sample showing wxDebugReport and related classes
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2005 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ----------------------------------------------------------------------------
14 // ----------------------------------------------------------------------------
21 #include "wx/msgdlg.h"
22 #include "wx/button.h"
23 #include "wx/dcclient.h"
25 #include "wx/datetime.h"
27 #include "wx/filename.h"
28 #include "wx/debugrpt.h"
30 #if !wxUSE_DEBUGREPORT
31 #error "This sample can't be built without wxUSE_DEBUGREPORT"
32 #endif // wxUSE_DEBUGREPORT
34 #if !wxUSE_ON_FATAL_EXCEPTION
35 #error "This sample can't be built without wxUSE_ON_FATAL_EXCEPTION"
36 #endif // wxUSE_ON_FATAL_EXCEPTION
38 #if !defined(__WXMSW__) && !defined(__WXPM__)
39 #include "../sample.xpm"
42 // ----------------------------------------------------------------------------
43 // custom debug reporting class
44 // ----------------------------------------------------------------------------
46 // this is your custom debug reporter: it will use curl program (which should
47 // be available) to upload the crash report to the given URL (which should be
49 class MyDebugReport
: public wxDebugReportUpload
52 MyDebugReport() : wxDebugReportUpload
54 wxT("http://your.url.here/"),
62 // this is called with the contents of the server response: you will
63 // probably want to parse the XML document in OnServerReply() instead of
64 // just dumping it as I do
65 virtual bool OnServerReply(const wxArrayString
& reply
)
67 if ( reply
.IsEmpty() )
69 wxLogError(wxT("Didn't receive the expected server reply."));
73 wxString
s(wxT("Server replied:\n"));
75 const size_t count
= reply
.GetCount();
76 for ( size_t n
= 0; n
< count
; n
++ )
78 s
<< wxT('\t') << reply
[n
] << wxT('\n');
81 wxLogMessage(wxT("%s"), s
.c_str());
87 // another possibility would be to build email library from contrib and use
88 // this class, after uncommenting it:
91 #include "wx/net/email.h"
93 class MyDebugReport
: public wxDebugReportCompress
96 virtual bool DoProcess()
98 if ( !wxDebugReportCompress::DoProcess() )
100 wxMailMessage
msg(GetReportName() + wxT(" crash report"),
101 wxT("vadim@wxwindows.org"),
102 wxEmptyString
, // mail body
103 wxEmptyString
, // from address
104 GetCompressedFileName(),
105 wxT("crashreport.zip"));
107 return wxEmail::Send(msg
);
113 // ----------------------------------------------------------------------------
115 // ----------------------------------------------------------------------------
117 // just some functions to get a slightly deeper stack trace
118 static void bar(const char *p
)
123 printf("bar: %s\n", p
);
126 void baz(const wxString
& s
)
128 printf("baz: %s\n", (const char*)s
.c_str());
139 // ----------------------------------------------------------------------------
141 // ----------------------------------------------------------------------------
145 DebugRpt_Quit
= wxID_EXIT
,
146 DebugRpt_Crash
= 100,
150 DebugRpt_About
= wxID_ABOUT
153 class MyFrame
: public wxFrame
159 void OnQuit(wxCommandEvent
& event
);
160 void OnReportForCrash(wxCommandEvent
& event
);
161 void OnReportForCurrent(wxCommandEvent
& event
);
162 void OnReportPaint(wxCommandEvent
& event
);
163 void OnReportUpload(wxCommandEvent
& event
);
164 void OnAbout(wxCommandEvent
& event
);
166 void OnPaint(wxPaintEvent
& event
);
169 // number of lines drawn in OnPaint()
172 wxDECLARE_NO_COPY_CLASS(MyFrame
);
173 DECLARE_EVENT_TABLE()
176 // ----------------------------------------------------------------------------
178 // ----------------------------------------------------------------------------
180 // this is a usual application class modified to work with debug reporter
182 // basically just 2 things are necessary: call wxHandleFatalExceptions() as
183 // early as possible and override OnFatalException() to create the report there
184 class MyApp
: public wxApp
187 // call wxHandleFatalExceptions here
190 // create our main window here
191 virtual bool OnInit();
193 // called when a crash occurs in this application
194 virtual void OnFatalException();
196 // this is where we really generate the debug report
197 void GenerateReport(wxDebugReport::Context ctx
);
199 // if this function is called, we'll use MyDebugReport which would try to
200 // upload the (next) generated debug report to its URL, otherwise we just
201 // generate the debug report and leave it in a local file
202 void UploadReport(bool doIt
) { m_uploadReport
= doIt
; }
207 wxDECLARE_NO_COPY_CLASS(MyApp
);
212 // ============================================================================
214 // ============================================================================
216 // ----------------------------------------------------------------------------
218 // ----------------------------------------------------------------------------
220 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
221 EVT_MENU(DebugRpt_Quit
, MyFrame::OnQuit
)
222 EVT_MENU(DebugRpt_Crash
, MyFrame::OnReportForCrash
)
223 EVT_MENU(DebugRpt_Current
, MyFrame::OnReportForCurrent
)
224 EVT_MENU(DebugRpt_Paint
, MyFrame::OnReportPaint
)
225 EVT_MENU(DebugRpt_Upload
, MyFrame::OnReportUpload
)
226 EVT_MENU(DebugRpt_About
, MyFrame::OnAbout
)
228 EVT_PAINT(MyFrame::OnPaint
)
232 : wxFrame(NULL
, wxID_ANY
, wxT("wxWidgets Debug Report Sample"),
233 wxDefaultPosition
, wxDefaultSize
, wxFULL_REPAINT_ON_RESIZE
|wxDEFAULT_FRAME_STYLE
)
237 SetIcon(wxICON(sample
));
239 wxMenu
*menuFile
= new wxMenu
;
240 menuFile
->Append(DebugRpt_Quit
, wxT("E&xit\tAlt-X"));
242 wxMenu
*menuReport
= new wxMenu
;
243 menuReport
->Append(DebugRpt_Crash
, wxT("Report for &crash\tCtrl-C"),
244 wxT("Provoke a crash inside the program and create report for it"));
245 menuReport
->Append(DebugRpt_Current
, wxT("Report for c&urrent context\tCtrl-U"),
246 wxT("Create report for the current program context"));
247 menuReport
->Append(DebugRpt_Paint
, wxT("Report for &paint handler\tCtrl-P"),
248 wxT("Provoke a repeatable crash in wxEVT_PAINT handler"));
249 menuReport
->AppendSeparator();
250 menuReport
->AppendCheckItem(DebugRpt_Upload
, wxT("Up&load debug report"),
251 wxT("You need to configure a web server accepting debug report uploads to use this function"));
253 wxMenu
*menuHelp
= new wxMenu
;
254 menuHelp
->Append(DebugRpt_About
, wxT("&About...\tF1"));
256 wxMenuBar
*mbar
= new wxMenuBar();
257 mbar
->Append(menuFile
, wxT("&File"));
258 mbar
->Append(menuReport
, wxT("&Report"));
259 mbar
->Append(menuHelp
, wxT("&Help"));
267 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
272 void MyFrame::OnReportForCrash(wxCommandEvent
& WXUNUSED(event
))
274 // this call is going to crash
279 void MyFrame::OnReportForCurrent(wxCommandEvent
& WXUNUSED(event
))
281 // example of manually generated report, this could be also
282 // used in wxApp::OnAssert()
283 wxGetApp().GenerateReport(wxDebugReport::Context_Current
);
286 void MyFrame::OnReportPaint(wxCommandEvent
& WXUNUSED(event
))
288 // this will result in a crash in OnPaint()
291 // ensure it's called immediately
295 void MyFrame::OnReportUpload(wxCommandEvent
& event
)
297 wxGetApp().UploadReport(event
.IsChecked());
300 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
304 wxT("wxDebugReport sample\n(c) 2005 Vadim Zeitlin <vadim@wxwindows.org>"),
305 wxT("wxWidgets Debug Report Sample"),
306 wxOK
| wxICON_INFORMATION
,
311 void MyFrame::OnPaint(wxPaintEvent
& WXUNUSED(event
))
314 const wxSize size
= GetClientSize();
315 for ( wxCoord x
= 0; x
< size
.x
; x
+= size
.x
/m_numLines
)
316 dc
.DrawLine(x
, 0, x
, size
.y
);
319 // ----------------------------------------------------------------------------
321 // ----------------------------------------------------------------------------
325 // user needs to explicitly enable this
326 m_uploadReport
= false;
328 // call this to tell the library to call our OnFatalException()
329 wxHandleFatalExceptions();
334 if ( !wxApp::OnInit() )
342 void MyApp::OnFatalException()
344 GenerateReport(wxDebugReport::Context_Exception
);
347 void MyApp::GenerateReport(wxDebugReport::Context ctx
)
349 wxDebugReportCompress
*report
= m_uploadReport
? new MyDebugReport
350 : new wxDebugReportCompress
;
352 // add all standard files: currently this means just a minidump and an
353 // XML file with system info and stack trace
356 // you can also call report->AddFile(...) with your own log files, files
357 // created using wxRegKey::Export() and so on, here we just add a test
358 // file containing the date of the crash
359 wxFileName
fn(report
->GetDirectory(), wxT("timestamp.my"));
360 wxFFile
file(fn
.GetFullPath(), wxT("w"));
361 if ( file
.IsOpened() )
363 wxDateTime dt
= wxDateTime::Now();
364 file
.Write(dt
.FormatISODate() + wxT(' ') + dt
.FormatISOTime());
368 report
->AddFile(fn
.GetFullName(), wxT("timestamp of this report"));
370 // can also add an existing file directly, it will be copied
373 report
->AddFile(wxT("c:\\autoexec.bat"), wxT("DOS startup file"));
375 report
->AddFile(wxT("/etc/motd"), wxT("Message of the day"));
378 // calling Show() is not mandatory, but is more polite
379 if ( wxDebugReportPreviewStd().Show(*report
) )
381 if ( report
->Process() )
383 if ( m_uploadReport
)
385 wxLogMessage(wxT("Report successfully uploaded."));
389 wxLogMessage(wxT("Report generated in \"%s\"."),
390 report
->GetCompressedFileName().c_str());
395 //else: user cancelled the report