Paint exceptions and error dialogs

In Delphi, every window message handler is automatically wrapped in a try..except. Exceptions are always handled, by showing the error text in a dialog box and letting the program continue execution (though you can globally override that behavior, or, obviously, add your own try..except if you need it). This global handler is good, except for paint exceptions. If your paint code raises an exception, you’re screwed, because the error dialog (usually, at least) pops up right on top of the control. When you close the error dialog, the control gets invalidated, it gets another paint message, and… boom, you immediately get another error dialog. Close that one, another immediately pops up. So there’s no way to close the application, other than killing it from the debugger or from Task Manager.

WinForms improves this a bit, by not catching paint exceptions. Any exception during painting will automatically terminate your program. Extremely crude, but effective enough; it’s actually a step forward from the infinite-dialog scenario. But WinForms doesn’t catch exceptions anywhere else, either — and that’s downright brain-damaged. If I click a button, and that button’s Click event handler does something that throws an InvalidOperationException, then my entire application exits. Say what??

In Delphi, we don’t have to think about exception handling; it just works (except in paint code, which doesn’t cause problems very often). In WinForms, we always have to think about exception handling. Much more work for us, for very little gain. Not a good thing.

So, in our app at work, we’ve been adding try..catch handlers in all (we hope) of the UI code. Including, as it turns out, the paint code, which was a bad idea on our part. Infinite dialogs this morning. Whee.

But I found a nice tidy way to exit the program, without summarily killing it. The whole problem is when closing the dialog forces the control to repaint. If closing the dialog doesn’t force the control to repaint, then all is well. So you just need to open Task Manager, set it to stay on top, and size it so that it completely covers the problem control (but not the parent window’s Close button). Then you can switch the focus back to the app, and keep hitting Enter to dismiss the dialogs. The control is covered by Task Manager, so it never gets another Paint event, so it doesn’t throw any more exceptions. Once all the error dialogs are gone, you can close the window without hassle.

(And no, we don’t have an exception handler on our WinForms paint code anymore. What we do have is a comment saying “DON’T CATCH EXCEPTIONS IN HERE!”.)

Holy cow, why didn’t anyone tell me about New EIP?

Holy cow. I found a blog post about a way-cool Visual Studio debugger feature… that’s also available in Delphi’s debugger… even for Win32! Sweeeet.

It’s a way to move the current execution pointer. How many times have you stepped over a function, realized it didn’t do what you wanted,

and wish you could step back? Well, as long as the function didn’t have any significant side effects (and, in Win32, as long as it didn’t smash any important registers), you can. Gotten into an infinite loop, and had to terminate the app and start over? Not necessary — you can just move the instruction pointer outside the loop and keep debugging.

In Visual Studio .NET, the feature is called “Set Next Statement” and is available right there in the code window’s context menu; just right-click on the line you want to move to. In Delphi for Win32, you have to open the CPU window, and then you can right-click on an instruction in there and use the ever-so-intuitively-named “New EIP” menu item. No wonder I never knew Delphi had this feature.

I’ll be curious to see how well this works, and how sensitive it really is to things like register usage (temporary variables?). But, man, oh, man. This is gonna be awesome…

TActionList for WinForms

I’ve missed TActionList and TAction since I started working in .NET. And now I may be able to get them back. Someone posted an article on CodeProject with an ActionList class for WinForms. Woo! I haven’t tried it yet, but if it works well, this could be cool.

Looks like they’re using IExtenderProvider, which I hadn’t thought about for actions but ought to work really well. Looks like a good design; you drop an ActionList on your form, it probably hooks Application.Idle so it can fire the actions’ Update events, and then you just create the actions and set the new Action property that appears on all your controls. I’ll have to see if it’s got everything you really need (caption, imagelist and image index, Visible, etc.). But even if it just gives me an easy way to share the caption, enabled status, and click-handler among several UI elements, that’d be a good start.

Thanks to Chris Woodruff for posting the link.

Distributed Refactoring

Eric Gunnerson (Program Manager on Microsoft’s C# team) has been blogging about his experiences at JavaOne. Since I’m not a Java programmer, I’ve just been skimming, but I noticed one bit that was extremely interesting:

One of the cool things that JBuilder does is distributed refactorings. This allows you to save a refactoring, ship it with a new version of your product, and then allow your client to apply that refactoring on their code to easily migrate to the new version.

One word: Wow.

Five more words: When can C# have that?? It’d be a fabulous feature for Delphi, too, especially if it was available for both .NET and Win32.

Just imagine if third-party control authors were free to refactor their public interfaces, and get rid of the cruft that invariably creeps in over time. Poorly-named properties, refactorings that move methods onto other classes… and being able to just do the refactoring, ship the new version of your control, and have everyone’s code automatically be brought up to date. Wow…

AVI Editing Library

Boy, what I wouldn’t have given to have found this AVI-editing library a couple of years ago. Build AVIs frame-by-frame, extract frames from an existing AVI, change compression, add sound, remove sound… wow. Comes with a sample app that lets you do all that from a GUI, or you can do it all from code.

The library is written in C#, but since Delphi is limited to AVIs for animation, the sample app would make a great utility for Delphi UI developers. (.NET programmers can just use animated GIFs…)

Update on .NET Services with Indy

I was just glancing back through my blog, and noticed that I said Windows services were easy if you’re using Indy’s HTTP server component. (Reasonably true, it seems.) I also said that all you need to do is set the server component’s Active property to true in your service’s OnStart, and back to false in your OnStop. (Well, that’s what I thought at the time.)

Turns out the thing to do in OnStop is to call TIdHttpServer.Free. Free calls Dispose, and Dispose sets Active to false, so it all works out; but if you don’t call Free, if for example you call Dispose instead, then the service EXE and DLLs won’t actually unload from memory for a good fifteen or twenty seconds afterward. Don’t ask me why; in Reflector, it sure doesn’t look like Free is doing anything significant besides calling Dispose. It’s all pretty puzzling. It also plays havoc with your pre- and post-build events that stop and restart your service so you can recompile it; when you say stop, it says it’s stopped, but really it wants to think about it for a while longer first.

Another mysterious thing is that, if you call Free, it will apparently (we found out) immediately terminate any client connections. This even though Free calls Dispose, which sets Active to false, and the setter for the Active property (at least this is what the code looked like) waits for all client-servicing threads to terminate before it returns. So it shouldn’t, near as I can tell, be terminating connections when you Free it, but it is. This is what we get for working with beta software.

Installing a folder with specified permissions

So for the next release of our software, we need our installer to create a folder that’s writable by all users on the computer.

You’d think this wouldn’t be hard. You’d think this would be well-trod ground. But no, apparently not. We’re using an MSI-based installer, nice feature set, rather pricey, which apparently can’t grant permissions to the standard “Users” group because it claims that group doesn’t exist. (We’ve filed a bug report and are waiting to hear back.) And our attempt to write a little app to set the permissions programmatically isn’t going well either. I’m not actually the developer who’s working on installation issues (I just get some questions bounced off me now and then), but it seems to be causing rapid hair loss — not from ripping hair out, just from the friction caused by banging against brick walls. I’ve looked at the permission APIs before, and they’re pretty awful; according to my cohort, the documentation is even worse, basically amounting to “take a guess at the parameters and see if it works”.

Freeware to the rescue.

My boss suggested that I take a quick look at Jordan Russell’s Inno Setup, a freeware (with source) installation-building package that I had some prior experience with, and see if it could handle permissions. It originally took me a while to get used to Inno, since you have to write a text-based install script. The first time I downloaded it (around five years ago), I took a look at it and then uninstalled it — I made the mistake of being unimpressed by its lack of a pretty design-time GUI. (It has syntax highlighting now, which helps, but you still write your script as a text file.) But it’s powerful, and it can do just about anything; it’s even got a built-in scripting language. Jordan pays attention to building good apps (none of that “every time the user clicks the Next button, we’ll hide the current dialog box and then show another one, and hope nobody notices the flickering” crap like Wise and InstallShield both seem to be doing these days), and of course free is good. But can it change permissions?

Of course it can change permissions. Yes, it can grant modify access on a given folder to all users of the computer (I just tested it to make absolutely sure that it works, and it does, even on the same PC where the expensive installer didn’t work). You just tack “; Permissions: users-modify” onto the entry in the [Dirs] section. So, while we probably won’t switch our installer to Inno at this point, we do have ready access to source code (Delphi, no less) for changing permissions.

As if that weren’t cool enough, the FAQ on the Inno Setup web site suggested taking a look at SetACL, an open-source, command-line tool for changing file permissions. SetACL.exe (command-line version) is 258K — which seems awfully large for a C++ console app — but its list of command-line parameters is pretty substantial; it can set permissions on files, folders, printers, Registry entries, services, and network shares, and it’s full of options I’ve never even heard of. I think, between Inno and SetACL, that our permission problems should be pretty well wrapped up. And there was much rejoicing.