NOTE ADDED AFTER SOLUTION: An AccessViolationException was being thrown inside the method called by reflection. This was the reason the TargetInvocationException couldn
Found the reason why I couldn't catch the exception:
The actual exception was an AccessViolationException, which can't be caught in dotnet 4.0 without taking special steps (How to handle AccessViolationException.)
To make things more fun, when AccessViolationException gets thrown in a method called by reflection, only a TargetInvocationException gets logged in the Windows event log, and only the TargetInvocationException is available in the dump.
Once I managed to get the real exception, I found that that it was a call to Application.DoEvents() from a non-GUI thread that caused the AccessViolation. DoEvents() can cause enough fun when called on the GUI-Thread (Use of Application.DoEvents()), let alone when called from a background thread.
Once that was fixed, I found that our third party library (the one with the copy protection) doesn't like being called simultaneously in separate instances. Fixing that was a matter of a synclock in the right place.
The code causing all of this fun was at one time all in the GUI-Thread, and was originally written back in the days of dotnet 1.1 - this explains the call to DoEvents. The code has been converted piece-wise to run in parallel in background threads through several different stages, with no one single developer having a complete overview of the process.