www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Show dialog box for uncaught exception (Windows, lld-link)

reply SimonN <eiderdaus gmail.com> writes:
Hi,

for Windows, I link my executables with `lld-link`, whether for 
32-bit and 64-bit and whether I've built with LDC or DMD.

How can I generate a dialog box for uncaught exceptions that fly 
out of my executable's `main()`?

When I linked with Optlink years ago for Windows 32-bit, it 
generated an error dialog box for an uncaught exception. But with 
`lld-link`, the exception's message lands only on stderr. I 
didn't see anything related in `lld-link -help`. Can I configure 
DRuntime in a special way at runtime?

My application is a graphical game. I close stdout and stderr by 
passing `-subsystem:windows` to `lld-link` to suppress the extra 
console window. For a few fatal errors (missing required 
resources, can't open display, ...), I throw exceptions, log them 
to logfile, then re-throw them to crash. I can tell Windows users 
to look in the logfile, but it would be more fitting on Windows 
to show an error dialog box in addition to the logging.

-- Simon
May 05
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Sunday, 5 May 2024 at 14:55:20 UTC, SimonN wrote:
 My application is a graphical game. I close stdout and stderr 
 by passing `-subsystem:windows` to `lld-link` to suppress the 
 extra console window. For a few fatal errors (missing required 
 resources, can't open display, ...), I throw exceptions, log 
 them to logfile, then re-throw them to crash. I can tell 
 Windows users to look in the logfile, but it would be more 
 fitting on Windows to show an error dialog box in addition to 
 the logging.
```d int realMain(string[] args) { // all your normal code goes here } int main(string[] args) { version(Windows) { try { realMain(args); } catch(Exception e) { visualDisplayOfException(e); throw e; } } else { // presumably, non-windows systems shouldn't show a graphical Exception // trace? realMain(args); } } ``` -Steve
May 05
parent reply SimonN <eiderdaus gmail.com> writes:
On Sunday, 5 May 2024 at 17:15:10 UTC, Steven Schveighoffer wrote:
         } catch(Exception e) {
             visualDisplayOfException(e);
             throw e;
         }
Thanks! That's practically the same pattern that I already use for logging: Try-catch near the entry point, show the message, re-throw. My implementation for the message box is now: catch (Throwable t) { import core.sys.windows.windows; const string errText = /* ... parse t ... */ MessageBoxA(null, errText.ptr, null, MB_ICONERROR); } That solves my problem. Even though I don't pass my game's window as the parent of the message box (first argument, where I pass `null`), the graphical game halts before exiting, shows the error, and users can screenshot both together. That's good. From your answer, I'll assume: There is no standardized way in the D ecosystem (e.g., by calling a DRuntime function from my usercode) to opt into displaying such a message box for uncaught exceptions. I have to call third-party APIs myself. Or is there something after all? From reading the 2019 thread [Deactivate windows MessageBox dialog on exception](https://forum.dlang.org/post/tlhjypvsaxzymccfcvsw forum.dlang.org), it sounds like we should get an error box when we link with `-subsystem:windows`, and no box otherwise. -- Simon
May 05
parent SimonN <eiderdaus gmail.com> writes:
On Sunday, 5 May 2024 at 18:28:29 UTC, SimonN wrote:
 My implementation for the message box is now:
According to [UTF-8 Everywhere](https://utf8everywhere.org/#windows), I shouldn't use `MessageBoxA` at all. The `A` means ANSI codepages, _not_ UTF-8. My above code _will_ show garbage output when there is some non-ASCII in the exception message. Better: Convert to UTF-16 yourself and call `MessageBoxW`: version (Windows) { import core.sys.windows.windows; import std.conv; const wstring messageBody = wtext(/* ... */, "\0"); MessageBoxW(null, messageBody.ptr, null, MB_ICONERROR); throw /* ... */; } -- Simon
May 05