@spazzarama and all, sorry about the super slow response. I was able to figure out what was causing my issue and then I finally had time to create a simple example. You can find the project here: https://github.com/jrswenson/HookService

So the original issue was I had a service that ran as the System user. Then the process I inject in to was ran as the current user. I wanted to wait for the Service process to exit and then exit the Run method. The root of the problem was 1: not running the Target Application as Admin, 2: Running the Target Application as a different user.

I went round and round trying different things. I finally settled on using a Global Mutex. This actually works really well. The service creates the Mutex and then the injected code waits for the Mutex to be release. The cool thing is that if the Thread that creates the Mutex exits with out first releasing the Mutex, the Mutex throws a AbandonedMutexException. So this allows the injected code to do a WaitOne() with out a timeout. I think the best part is this works if the service shut down gracefully or if the process is killed for some reason.