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