Thread overview
Show dialog box for uncaught exception (Windows, lld-link)
May 05
SimonN
May 05
SimonN
May 06
SimonN
May 05

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

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.

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

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, it sounds like we should get an error box when we link with -subsystem:windows, and no box otherwise.

-- Simon

May 06

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, 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