Why rebuild VB6 applications?

We have a system with 1+ million lines of code, developed in Visual Basic 6 with rather less than "best" practices. But it mostly fulfills the business requirements, and we have a team who can keep up with the really essential changes. The developers have talked for a long time about how we're going to replace it with something more modern, but my supervisor recently asked "why?" Couldn't the effort be put into something that delivers more direct business value, regardless of how much easier maintenance might be after a rewrite? It works, so why fix it? Needless to say, that took the wind out of my sails, but I actually started to agree after considering it for a while.

I also spoke with Lisa Feigenbaum, Microsoft Program Manager for Visual Studio Languauges, after the Orlando VS 2010 launch event last night. She was curious about our continued use of VB6 and any plans or attempts to transition to .NET (and I admire her tolerance for my shortcomings as a conversationalist). She mentioned the Interop Forms Toolkit, which would help dramatically in a gradual transition... and replace months of my own effort at making VB6 events cooperate with both COM interfaces and the .NET event system. Thanks, Lisa. :)

The first question is of course "why don't you just run the upgrade wizard?" A couple dozen EXE files, hundreds of DLLs mostly being used as flat function libraries to keep the EXE compile time down, all code from data access to UI events embedded in every form, deprecated COM UI tookits, and a database schema that would desperately need cleaning if the code weren't dependent on it being exactly as-is in so many places... that's a good start at an answer. It'd take forever to convert and test completely, and I can understand that being a losing business value proposition. Yes, we might then be able to refactor a little more easily, but it'd make more sense to generate a consistent design in partial rewrites than to convert everything just to scrap as much as possible.

But I think I've found one answer: We cannot safely build a web site that can update data, using the database as the system interface. New code would always use parameterized command objects or similar to prevent SQL injection, but that doesn't stop an unsafe string, e.g.
'; Frobnicate AReallyImportantTable;--
from being put in the database. Granted, the web app would just treat it as a string value, not a statement. But the VB6 app isn't fully SQL injection resistant. So a web user could insert an "evil" string value, then an unsuspecting VB6 app user could open that record, make a change elsewhere, and commit it back. Now the evil value is part of the SQL statement, and executes under the context of a slightly more trusted user.

Sure, we could try to strip out all dangerous characters, but I've seen some tricks with high-Unicode characters that get converted to a special character somewhere along the way. I don't know if the list I saw was exhaustive, or whether we'd get the implementation exactly right. And I don't want my tables frobnicated if I can help it. :)

The solution would be to rewrite any VB6 code that updates the same table whenever we make some of the data web editable. We'd have to make sure everything was parameterized, which is non-trivial in VB6. And it's still two separate pieces of code responsible for the same action, and enforcing the business logic, but that's just a developer maintenance headache, not necessarily a business one.

But if we're doing a rewrite of part of our VB6 app anyway, and we can use the Interop Toolkit or similar, and then we can share the business logic across the web and the Windows app... then we might have a case where the cost of writing it in .NET is at least in the same ballpark. And the argument about the ease of future maintenance (and finding new employees who can do it) might tip the balance in favor of .NET.