]>
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 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ----------------------------------------------------------------------------
14 // ----------------------------------------------------------------------------
19 #include "wx/msgdlg.h"
20 #include "wx/button.h"
22 #include "wx/datetime.h"
24 #include "wx/filename.h"
25 #include "wx/debugrpt.h"
27 #if !wxUSE_DEBUGREPORT
28 #error "This sample can't be built without wxUSE_DEBUGREPORT"
29 #endif // wxUSE_DEBUGREPORT
31 #if !wxUSE_ON_FATAL_EXCEPTION
32 #error "This sample can't be built without wxUSE_ON_FATAL_EXCEPTION"
33 #endif // wxUSE_ON_FATAL_EXCEPTION
35 #if !defined(__WXMSW__) && !defined(__WXPM__)
36 #include "../sample.xpm"
39 // ----------------------------------------------------------------------------
40 // custom debug reporting class
41 // ----------------------------------------------------------------------------
43 // this is your custom debug reporter: it will use curl program (which should
44 // be available) to upload the crash report to the given URL (which should be
46 class MyDebugReport
: public wxDebugReportUpload
49 MyDebugReport() : wxDebugReportUpload
51 _T("http://your.url.here/"),
59 // this is called with the contents of the server response: you will
60 // probably want to parse the XML document in OnServerReply() instead of
61 // just dumping it as I do
62 virtual bool OnServerReply(const wxArrayString
& reply
)
64 if ( reply
.IsEmpty() )
66 wxLogError(_T("Didn't receive the expected server reply."));
70 wxString
s(_T("Server replied:\n"));
72 const size_t count
= reply
.GetCount();
73 for ( size_t n
= 0; n
< count
; n
++ )
75 s
<< _T('\t') << reply
[n
] << _T('\n');
78 wxLogMessage(_T("%s"), s
.c_str());
84 // another possibility would be to build email library from contrib and use
85 // this class, after uncommenting it:
88 #include "wx/net/email.h"
90 class MyDebugReport
: public wxDebugReportCompress
93 virtual bool DoProcess()
95 if ( !wxDebugReportCompress::DoProcess() )
97 wxMailMessage
msg(GetReportName() + _T(" crash report"),
98 _T("vadim@wxwindows.org"),
99 wxEmptyString
, // mail body
100 wxEmptyString
, // from address
101 GetCompressedFileName(),
102 _T("crashreport.zip"));
104 return wxEmail::Send(msg
);
110 // ----------------------------------------------------------------------------
112 // ----------------------------------------------------------------------------
114 // just some functions to get a slightly deeper stack trace
115 static void bar(const wxChar
*p
)
120 printf("bar: %s\n", p
);
123 void baz(const wxString
& s
)
125 printf("baz: %s\n", s
.c_str());
136 // ----------------------------------------------------------------------------
138 // ----------------------------------------------------------------------------
142 DebugRpt_Quit
= wxID_EXIT
,
143 DebugRpt_Crash
= 100,
146 DebugRpt_About
= wxID_ABOUT
149 class MyFrame
: public wxFrame
155 void OnQuit(wxCommandEvent
& event
);
156 void OnReportForCrash(wxCommandEvent
& event
);
157 void OnReportForCurrent(wxCommandEvent
& event
);
158 void OnReportUpload(wxCommandEvent
& event
);
159 void OnAbout(wxCommandEvent
& event
);
161 DECLARE_NO_COPY_CLASS(MyFrame
)
162 DECLARE_EVENT_TABLE()
165 // ----------------------------------------------------------------------------
167 // ----------------------------------------------------------------------------
169 // this is a usual application class modified to work with debug reporter
171 // basically just 2 things are necessary: call wxHandleFatalExceptions() as
172 // early as possible and override OnFatalException() to create the report there
173 class MyApp
: public wxApp
176 // call wxHandleFatalExceptions here
179 // create our main window here
180 virtual bool OnInit();
182 // called when a crash occurs in this application
183 virtual void OnFatalException();
185 // this is where we really generate the debug report
186 void GenerateReport(wxDebugReport::Context ctx
);
188 // if this function is called, we'll use MyDebugReport which would try to
189 // upload the (next) generated debug report to its URL, otherwise we just
190 // generate the debug report and leave it in a local file
191 void UploadReport(bool doIt
) { m_uploadReport
= doIt
; }
196 DECLARE_NO_COPY_CLASS(MyApp
)
201 // ============================================================================
203 // ============================================================================
205 // ----------------------------------------------------------------------------
207 // ----------------------------------------------------------------------------
209 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
210 EVT_MENU(DebugRpt_Quit
, MyFrame::OnQuit
)
211 EVT_MENU(DebugRpt_Crash
, MyFrame::OnReportForCrash
)
212 EVT_MENU(DebugRpt_Current
, MyFrame::OnReportForCurrent
)
213 EVT_MENU(DebugRpt_Upload
, MyFrame::OnReportUpload
)
214 EVT_MENU(DebugRpt_About
, MyFrame::OnAbout
)
218 : wxFrame(NULL
, wxID_ANY
, _T("wxWidgets Debug Report Sample"))
220 SetIcon(wxICON(sample
));
222 wxMenu
*menuFile
= new wxMenu
;
223 menuFile
->Append(DebugRpt_Quit
, _T("E&xit\tAlt-X"));
225 wxMenu
*menuReport
= new wxMenu
;
226 menuReport
->Append(DebugRpt_Crash
, _T("Report for &crash\tCtrl-C"),
227 _T("Provoke a crash inside the program and create report for it"));
228 menuReport
->Append(DebugRpt_Current
, _T("Report for c&urrent context\tCtrl-U"),
229 _T("Create report for the current program context"));
230 menuReport
->AppendSeparator();
231 menuReport
->AppendCheckItem(DebugRpt_Upload
, _T("Up&load debug report"),
232 _T("You need to configure a web server accepting debug report uploads to use this function"));
234 wxMenu
*menuHelp
= new wxMenu
;
235 menuHelp
->Append(DebugRpt_About
, _T("&About...\tF1"));
237 wxMenuBar
*mbar
= new wxMenuBar();
238 mbar
->Append(menuFile
, _T("&File"));
239 mbar
->Append(menuReport
, _T("&Report"));
240 mbar
->Append(menuHelp
, _T("&Help"));
248 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
253 void MyFrame::OnReportForCrash(wxCommandEvent
& WXUNUSED(event
))
255 // this call is going to crash
260 void MyFrame::OnReportForCurrent(wxCommandEvent
& WXUNUSED(event
))
262 // example of manually generated report, this could be also
263 // used in wxApp::OnAssert()
264 wxGetApp().GenerateReport(wxDebugReport::Context_Current
);
267 void MyFrame::OnReportUpload(wxCommandEvent
& event
)
269 wxGetApp().UploadReport(event
.IsChecked());
272 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
276 _T("wxDebugReport sample\n(c) 2005 Vadim Zeitlin <vadim@wxwindows.org>"),
277 _T("wxWidgets Debug Report Sample"),
278 wxOK
| wxICON_INFORMATION
,
283 // ----------------------------------------------------------------------------
285 // ----------------------------------------------------------------------------
289 // user needs to explicitely enable this
290 m_uploadReport
= false;
292 // call this to tell the library to call our OnFatalException()
293 wxHandleFatalExceptions();
298 if ( !wxApp::OnInit() )
306 void MyApp::OnFatalException()
308 GenerateReport(wxDebugReport::Context_Exception
);
311 void MyApp::GenerateReport(wxDebugReport::Context ctx
)
313 wxDebugReportCompress
*report
= m_uploadReport
? new MyDebugReport
314 : new wxDebugReportCompress
;
316 // add all standard files: currently this means just a minidump and an
317 // XML file with system info and stack trace
320 // you can also call report->AddFile(...) with your own log files, files
321 // created using wxRegKey::Export() and so on, here we just add a test
322 // file containing the date of the crash
323 wxFileName
fn(report
->GetDirectory(), _T("timestamp.my"));
324 wxFFile
file(fn
.GetFullPath(), _T("w"));
325 if ( file
.IsOpened() )
327 wxDateTime dt
= wxDateTime::Now();
328 file
.Write(dt
.FormatISODate() + _T(' ') + dt
.FormatISOTime());
332 report
->AddFile(fn
.GetFullName(), _T("timestamp of this report"));
334 // can also add an existing file directly, it will be copied
337 report
->AddFile(_T("c:\\autoexec.bat"), _T("DOS startup file"));
339 report
->AddFile(_T("/etc/motd"), _T("Message of the day"));
342 // calling Show() is not mandatory, but is more polite
343 if ( wxDebugReportPreviewStd().Show(*report
) )
345 if ( report
->Process() )
347 if ( m_uploadReport
)
349 wxLogMessage(_T("Report successfully uploaded."));
353 wxLogMessage(_T("Report generated in \"%s\"."),
354 report
->GetCompressedFileName().c_str());
359 //else: user cancelled the report