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