modified AddFile() to copy file to the debug report directory if its path is absolute
[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 wxHandleFatalExceptions();
141
142 if ( !wxApp::OnInit() )
143 return false;
144
145 return true;
146 }
147
148 virtual int OnRun()
149 {
150 // a real program would be presumably be a bit harder to crash than
151 // just pressing "yes" in a dialog... but this is just an example
152 switch ( wxMessageBox
153 (
154 _T("Generate report for crash (or just current context)?"),
155 _T("wxDebugReport Test"),
156 wxYES_NO | wxCANCEL
157 ) )
158 {
159 case wxYES:
160 // this call is going to crash
161 foo(32);
162 foo(17);
163 break;
164
165 case wxNO:
166 // example of manually generated report, this could be also
167 // used in wxApp::OnAssert()
168 GenerateReport(wxDebugReport::Context_Current);
169 break;
170
171 case wxCANCEL:
172 break;
173 }
174
175 return 0;
176 }
177
178 virtual void OnFatalException()
179 {
180 GenerateReport(wxDebugReport::Context_Exception);
181 }
182
183 void GenerateReport(wxDebugReport::Context ctx)
184 {
185 MyDebugReport report;
186
187 // add all standard files: currently this means just a minidump and an
188 // XML file with system info and stack trace
189 report.AddAll(ctx);
190
191 // you can also call report.AddFile(...) with your own log files, files
192 // created using wxRegKey::Export() and so on, here we just add a test
193 // file containing the date of the crash
194 wxFileName fn(report.GetDirectory(), _T("timestamp.my"));
195 wxFFile file(fn.GetFullPath(), _T("w"));
196 if ( file.IsOpened() )
197 {
198 wxDateTime dt = wxDateTime::Now();
199 file.Write(dt.FormatISODate() + _T(' ') + dt.FormatISOTime());
200 file.Close();
201 }
202
203 report.AddFile(fn.GetFullName(), _T("timestamp of this report"));
204
205 // can also add an existing file directly, it will be copied
206 // automatically
207 #ifdef __WXMSW__
208 report.AddFile(_T("c:\\autoexec.bat"), _T("DOS startup file"));
209 #else
210 report.AddFile(_T("/etc/motd"), _T("Message of the day"));
211 #endif
212
213 // calling Show() is not mandatory, but is more polite
214 if ( wxDebugReportPreviewStd().Show(report) )
215 {
216 if ( report.Process() )
217 {
218 // report successfully uploaded
219 }
220 }
221 //else: user cancelled the report
222 }
223 };
224
225 IMPLEMENT_APP(MyApp)
226