added wxDebugReport
[wxWidgets.git] / samples / debugrpt / debugrpt.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: debugrpt.cpp
3 // Purpose: minimal sample showing wxDebugReport and related classes
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 2005-01-20
7 // RCS-ID: $Id$
8 // Copyright: (c) 2005 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ----------------------------------------------------------------------------
13 // headers
14 // ----------------------------------------------------------------------------
15
16 #include "wx/app.h"
17 #include "wx/datetime.h"
18 #include "wx/ffile.h"
19 #include "wx/filename.h"
20 #include "wx/dynlib.h"
21 #include "wx/debugrpt.h"
22
23 #include "wx/msgdlg.h"
24
25 #if !wxUSE_DEBUGREPORT
26 #error "This sample can't be built without wxUSE_DEBUGREPORT"
27 #endif // wxUSE_DEBUGREPORT
28
29 // ----------------------------------------------------------------------------
30 // custom debug reporting class
31 // ----------------------------------------------------------------------------
32
33 // this is your custom debug reporter, you will probably want to parse the XML
34 // document in OnServerReply() instead of just dumping it as I do
35 class MyDebugReport : public wxDebugReportUpload
36 {
37 public:
38 MyDebugReport() : wxDebugReportUpload
39 (
40 _T("http://iml2.hitchcock.org/intranet/crashes/wxtest"),
41 _T("report:file"),
42 _T("action")
43 )
44 {
45 }
46
47 protected:
48 virtual bool OnServerReply(const wxArrayString& reply)
49 {
50 if ( reply.IsEmpty() )
51 {
52 wxLogError(_T("Didn't receive the expected server reply."));
53 return false;
54 }
55
56 wxString s(_T("Server replied:\n"));
57
58 const size_t count = reply.GetCount();
59 for ( size_t n = 0; n < count; n++ )
60 {
61 s << _T('\t') << reply[n] << _T('\n');
62 }
63
64 wxLogMessage(_T("%s"), s.c_str());
65
66 return true;
67 }
68 };
69
70 // ----------------------------------------------------------------------------
71 // helper functions
72 // ----------------------------------------------------------------------------
73
74 // just some functions to get a slightly deeper stack trace
75 static void bar(const wxChar *p)
76 {
77 char *pc = 0;
78 *pc = *p;
79
80 printf("bar: %s\n", p);
81 }
82
83 void baz(const wxString& s)
84 {
85 printf("baz: %s\n", s.c_str());
86 }
87
88 void foo(int n)
89 {
90 if ( n % 2 )
91 baz(wxT("odd"));
92 else
93 bar(wxT("even"));
94 }
95
96 // ----------------------------------------------------------------------------
97 // application class
98 // ----------------------------------------------------------------------------
99
100 // this is a usual application class modified to work with debug reporter
101 //
102 // basically just 2 things are necessary: call wxHandleFatalExceptions() as
103 // early as possible and override OnFatalException() to create the report there
104 class MyApp : public wxApp
105 {
106 public:
107 virtual bool OnInit()
108 {
109 wxHandleFatalExceptions();
110
111 if ( !wxApp::OnInit() )
112 return false;
113
114 return true;
115 }
116
117 virtual int OnRun()
118 {
119 // a real program would be presumably be a bit harder to crash than
120 // just pressing "yes" in a dialog... but this is just an example
121 switch ( wxMessageBox
122 (
123 _T("Generate report for crash (or just current context)?"),
124 _T("wxDebugReport Test"),
125 wxYES_NO | wxCANCEL
126 ) )
127 {
128 case wxYES:
129 // this call is going to crash
130 foo(32);
131 foo(17);
132 break;
133
134 case wxNO:
135 // example of manually generated report, this could be also
136 // used in wxApp::OnAssert()
137 GenerateReport(wxDebugReport::Context_Curent);
138 break;
139
140 case wxCANCEL:
141 break;
142 }
143
144 return 0;
145 }
146
147 virtual void OnFatalException()
148 {
149 GenerateReport(wxDebugReport::Context_Exception);
150 }
151
152 void GenerateReport(wxDebugReport::Context ctx)
153 {
154 MyDebugReport report;
155
156 // add all standard files: currently this means just a minidump and an
157 // XML file with system info and stack trace
158 report.AddAll(ctx);
159
160 // you can also call report.AddFile(...) with your own log files, files
161 // created using wxRegKey::Export() and so on, here we just add a test
162 // file containing the date of the crash
163 wxFileName fn(report.GetDirectory(), _T("timestamp.my"));
164 wxFFile file(fn.GetFullPath(), _T("w"));
165 if ( file.IsOpened() )
166 {
167 wxDateTime dt = wxDateTime::Now();
168 file.Write(dt.FormatISODate() + _T(' ') + dt.FormatISOTime());
169 file.Close();
170 }
171
172 report.AddFile(fn.GetFullName(), _T("timestamp of this report"));
173
174 // calling Show() is not mandatory, but is more polite
175 if ( wxDebugReportPreviewStd().Show(report) )
176 {
177 if ( report.Process() )
178 {
179 // report successfully uploaded
180 }
181 }
182 //else: user cancelled the report
183 }
184 };
185
186 IMPLEMENT_APP(MyApp)
187