]>
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 | ||
30 | // ---------------------------------------------------------------------------- | |
31 | // custom debug reporting class | |
32 | // ---------------------------------------------------------------------------- | |
33 | ||
fdc1aa52 VZ |
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) | |
ce4fd7b5 VZ |
37 | class MyDebugReport : public wxDebugReportUpload |
38 | { | |
39 | public: | |
40 | MyDebugReport() : wxDebugReportUpload | |
41 | ( | |
985604c1 | 42 | _T("http://your.url.here/"), |
ce4fd7b5 VZ |
43 | _T("report:file"), |
44 | _T("action") | |
45 | ) | |
46 | { | |
47 | } | |
48 | ||
49 | protected: | |
fdc1aa52 VZ |
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 | |
ce4fd7b5 VZ |
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 | ||
ed99e548 VZ |
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 | ||
ce4fd7b5 VZ |
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() | |
478cde32 | 168 | GenerateReport(wxDebugReport::Context_Current); |
ce4fd7b5 VZ |
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 | ||
fdc1aa52 VZ |
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 | ||
ce4fd7b5 VZ |
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 |