The uninstall wizard displayed a long list of rundll32 processes that had open files and this prevented the removal of my Exchange 2010 server:
In order to see which process holds files open, I had to know what was loaded with rundll32. At this point, however, the only clue I had was the process ID, a.k.a. PID. Not very useful.
It is not all gloom and doom though. Task Manager is a very useful troubleshooting beast, with lots of information hidden from the default view.
In my case I had to see what was loaded with rundll32. Let's look specifically at PID 7172, the first in the pre-flight check error report.
In Task Manager, I enabled the Command Line column...
... which then showed me the path to the DLL that was loaded in the process:
Doing a quick Google search on pla.dll, it looked like the files were open by the Performance Logs & Alerts service. Indeed, this service was started:
I disabled _and_ stopped the service, ...
... retried the uninstall wizard, and voilà, the pre-flight check succeeded:
IMPORTANT: Stating the obvious, it is not sufficient to just _disable_ the service. You must also _stop_ it to make sure it releases all file locks and resources. Disabling it ensures that the service doesn't start and lock files while in the middle of uninstalling Exchange, while stopping it actually releases the file locks.
In a similar way, we can identify any process that may hold files open when uninstalling not only Exchange 2010 but other software too.
Takeaway: Add the Performance Logs & Alerts service to the list of services to disable when uninstalling Exchange 2010, or perhaps any other version of Exchange server as a matter of fact.