Handle Memory-Leaking COM EXE Servers on a remote machine

By Peter Bromberg

Working with EXE COM Servers (MapPoint.exe, Excel.exe, and others) can be a daunting task if you have a large amount of repetitive processing, say on a threadpool. Often these babies will have a small memory leak eventually resulting in out of memory OS errors. If this happens on a remote server, you could be sunk, because most likely you will not be able to even remote into a frozen box.

All the tricks we've learned -- Marshal.ReleaseComObject, GC.Collect, etc. may not work with these EXE babies. In addition, killing the COM Server process and starting a new one may also not work.

I have to process many hundreds of thousands of SQL Server records with one of these COM Servers, and the memory usage continues to grow over time. I can't let one of these run overnight because the machine would likely be hobbled and completely unusable by the next day. So I came up with a last-resort "brute force" technique that seems ugly, but - it works!

What I do is count the number of iterations, and every time the process clocks an even 10,000 (or whatever number you have determined), I kill the COM Server, stop processing on the Threadpool, and spin up a brand new instance of my same app, which starts a new COM Server with a very low initial memory footprint. The original instance is exited gracefully. In this manner, I can have my process running for days on end with no fear of memory problems. Whenever a new instance starts, it automatically picks up at the next row in the SQL Server table that has not yet been processed and carries on for the next 10,000 rows.



// This is at the end of my Threadpool callback method
// Each time through the loop in the threadpool callback,  I check if counter id mod 10000 = zero
if (id % 10000 == 0)
    {  
       //we have passed 10,000 iterations, so...
Kill(id);
    }

// This method kills off the COM server, stops processing, spawns a brand new instance, and exits the original
  private static void Kill( int id)
        {

            Console.WriteLine("Recycling at " + id.ToString());
           ProcessUtil.KillProcess();  // kill off the COM Server EXE process that has been growing out of control
            mre.Set(); // /stop threadpool processing
    // start a brand new instance of this same exe process
           System.Diagnostics.Process.Start(System.Environment.CurrentDirectory + @"\YourProgram.exe");
  //  exit the original gracefully
           System.Environment.Exit(0);
           // DONE!
        }


//this is a utility class to kill all instances of a given process, e.g. "Excel"
public static  class ProcessUtil
    {
       public static void KillProcess()
      {           
           foreach (Process clsProcess in Process.GetProcesses())
  {
               if (clsProcess.ProcessName.StartsWith("YourExeComServerName"))
             {
                       clsProcess.Kill();
                    Console.WriteLine("KILLED IT.");
                        
             }
          }
      }
    }

Handle Memory-Leaking COM EXE Servers on a remote machine  (991 Views)