Compilation fix. I didn't add a #error since I figured this sample will be
[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/log.h"
18 #include "wx/datetime.h"
19 #include "wx/ffile.h"
20 #include "wx/filename.h"
21 #include "wx/dynlib.h"
22 #include "wx/debugrpt.h"
23
24 #include "wx/msgdlg.h"
25
26 #if !wxUSE_DEBUGREPORT
27 #error "This sample can't be built without wxUSE_DEBUGREPORT"
28 #endif // wxUSE_DEBUGREPORT
29
30 // ----------------------------------------------------------------------------
31 // custom debug reporting class
32 // ----------------------------------------------------------------------------
33
34 // this is your custom debug reporter: it will use curl program (which should
35 // be available) to upload the crash report to the given URL (which should be
36 // set up by you)
37 class MyDebugReport : public wxDebugReportUpload
38 {
39 public:
40 MyDebugReport() : wxDebugReportUpload
41 (
42 _T("http://your.url.here/"),
43 _T("report:file"),
44 _T("action")
45 )
46 {
47 }
48
49 protected:
50 // this is called with the contents of the server response: you will
51 // probably want to parse the XML document in OnServerReply() instead of
52 // just dumping it as I do
53 virtual bool OnServerReply(const wxArrayString& reply)
54 {
55 if ( reply.IsEmpty() )
56 {
57 wxLogError(_T("Didn't receive the expected server reply."));
58 return false;
59 }
60
61 wxString s(_T("Server replied:\n"));
62
63 const size_t count = reply.GetCount();
64 for ( size_t n = 0; n < count; n++ )
65 {
66 s << _T('\t') << reply[n] << _T('\n');
67 }
68
69 wxLogMessage(_T("%s"), s.c_str());
70
71 return true;
72 }
73 };
74
75 // another possibility would be to build email library from contrib and use
76 // this class, after uncommenting it:
77 #if 0
78
79 #include "wx/net/email.h"
80
81 class MyDebugReport : public wxDebugReportCompress
82 {
83 public:
84 virtual bool DoProcess()
85 {
86 if ( !wxDebugReportCompress::DoProcess() )
87 return false;
88 wxMailMessage msg(GetReportName() + _T(" crash report"),
89 _T("vadim@wxwindows.org"),
90 wxEmptyString, // mail body
91 wxEmptyString, // from address
92 GetCompressedFileName(),
93 _T("crashreport.zip"));
94
95 return wxEmail::Send(msg);
96 }
97 };
98
99 #endif // 0
100
101 // ----------------------------------------------------------------------------
102 // helper functions
103 // ----------------------------------------------------------------------------
104
105 // just some functions to get a slightly deeper stack trace
106 static void bar(const wxChar *p)
107 {
108 char *pc = 0;
109 *pc = *p;
110
111 printf("bar: %s\n", p);
112 }
113
114 void baz(const wxString& s)
115 {
116 printf("baz: %s\n", s.c_str());
117 }
118
119 void foo(int n)
120 {
121 if ( n % 2 )
122 baz(wxT("odd"));
123 else
124 bar(wxT("even"));
125 }
126
127 // ----------------------------------------------------------------------------
128 // application class
129 // ----------------------------------------------------------------------------
130
131 // this is a usual application class modified to work with debug reporter
132 //
133 // basically just 2 things are necessary: call wxHandleFatalExceptions() as
134 // early as possible and override OnFatalException() to create the report there
135 class MyApp : public wxApp
136 {
137 public:
138 virtual bool OnInit()
139 {
140 #if wxUSE_ON_FATAL_EXCEPTION
141 wxHandleFatalExceptions();
142 #endif
143
144 if ( !wxApp::OnInit() )
145 return false;
146
147 return true;
148 }
149
150 virtual int OnRun()
151 {
152 // a real program would be presumably be a bit harder to crash than
153 // just pressing "yes" in a dialog... but this is just an example
154 switch ( wxMessageBox
155 (
156 _T("Generate report for crash (or just current context)?"),
157 _T("wxDebugReport Test"),
158 wxYES_NO | wxCANCEL
159 ) )
160 {
161 case wxYES:
162 // this call is going to crash
163 foo(32);
164 foo(17);
165 break;
166
167 case wxNO:
168 // example of manually generated report, this could be also
169 // used in wxApp::OnAssert()
170 GenerateReport(wxDebugReport::Context_Current);
171 break;
172
173 case wxCANCEL:
174 break;
175 }
176
177 return 0;
178 }
179
180 virtual void OnFatalException()
181 {
182 GenerateReport(wxDebugReport::Context_Exception);
183 }
184
185 void GenerateReport(wxDebugReport::Context ctx)
186 {
187 MyDebugReport report;
188
189 // add all standard files: currently this means just a minidump and an
190 // XML file with system info and stack trace
191 report.AddAll(ctx);
192
193 // you can also call report.AddFile(...) with your own log files, files
194 // created using wxRegKey::Export() and so on, here we just add a test
195 // file containing the date of the crash
196 wxFileName fn(report.GetDirectory(), _T("timestamp.my"));
197 wxFFile file(fn.GetFullPath(), _T("w"));
198 if ( file.IsOpened() )
199 {
200 wxDateTime dt = wxDateTime::Now();
201 file.Write(dt.FormatISODate() + _T(' ') + dt.FormatISOTime());
202 file.Close();
203 }
204
205 report.AddFile(fn.GetFullName(), _T("timestamp of this report"));
206
207 // can also add an existing file directly, it will be copied
208 // automatically
209 #ifdef __WXMSW__
210 report.AddFile(_T("c:\\autoexec.bat"), _T("DOS startup file"));
211 #else
212 report.AddFile(_T("/etc/motd"), _T("Message of the day"));
213 #endif
214
215 // calling Show() is not mandatory, but is more polite
216 if ( wxDebugReportPreviewStd().Show(report) )
217 {
218 if ( report.Process() )
219 {
220 // report successfully uploaded
221 }
222 }
223 //else: user cancelled the report
224 }
225 };
226
227 IMPLEMENT_APP(MyApp)
228