Forum Discussion

dzrtfox's avatar
dzrtfox
Contributor
14 years ago

COM Interop Memory Leak?

Hi, I am running into an issue while automating TestExecute using COM Interop.  I have created a C# class to run script routines through COM.  As each test runs, the memory usage displayed for TestExecute in the Windows Task Manager continues to grow until the entire test run gets brought to its knees. 



I am not an expert at COM and may be doing something incorrectly.  Here is how I have it set up:



When the class is first initialized, I execute this routine to open the project suite:



public static bool OpenTCProject()

        {

            const string projectSuitePath = "C:\\AtlasAutomation\\AtlasAutomationSuite\\AtlasAutomationSuite.pjs";

            object TestExecuteObject = null;

            ITestCompleteCOMManager TestExecuteManager = null;

            ItcIntegration IntegrationObject = null;



            try

            {

                TestExecuteObject = Marshal.GetActiveObject(TEProgID);

            }

            catch

            {

                try

                {

                    TestExecuteObject = Activator.CreateInstance(Type.GetTypeFromProgID(TEProgID));

                }

                catch

                {

                }

            }



            if (TestExecuteObject == null)

            {

                return false;

            }



            try

            {

                TestExecuteManager = (ITestCompleteCOMManager)TestExecuteObject;

                IntegrationObject = TestExecuteManager.Integration;

                IntegrationObject.OpenProjectSuite(projectSuitePath);



                if (!IntegrationObject.IsProjectSuiteOpened())

                {

                    return false;

                }



                return true;

            }

            catch

            {

                return false;

            }

            finally

            {

                Marshal.ReleaseComObject(IntegrationObject);

                Marshal.ReleaseComObject(TestExecuteManager);

                Marshal.ReleaseComObject(TestExecuteObject);



                IntegrationObject = null;

                TestExecuteManager = null;

                TestExecuteObject = null;

            }

        }



The idea here is to only open the project suite once, at the beginning of the test run.  This works fine and opens the project suite as expected (and returns a boolean value indicating success/failure in opening the project).  Now for each test I run this method:



public static bool RunTest(string projectName, string testName)

        {

            object TestExecuteObject = Marshal.GetActiveObject(TEProgID);

            ITestCompleteCOMManager TestExecuteManager = (ITestCompleteCOMManager)TestExecuteObject;

            ItcIntegration IntegrationObject = TestExecuteManager.Integration;



            try

            {

                IntegrationObject.RunRoutine(projectName, testName, "Main");



                while (IntegrationObject.IsRunning())

                    Thread.Sleep(2000);



                if (IntegrationObject.GetLastResultDescription().Status == TC_LOG_STATUS.lsError)

                {

                    return false;

                }

                else

                {

                    return true;

                }

            }

            catch

            {

                return false;

            }

            finally

            {

                Marshal.ReleaseComObject(IntegrationObject);

                Marshal.ReleaseComObject(TestExecuteManager);

                Marshal.ReleaseComObject(TestExecuteObject);



                IntegrationObject = null;

                TestExecuteManager = null;

                TestExecuteObject = null;

            }

        }



Finally, I have a cleanup method that runs when the class is destructed:



public static void Cleanup()

        {

            object TestExecuteObject = Marshal.GetActiveObject(TEProgID);

            ITestCompleteCOMManager TestExecuteManager = (ITestCompleteCOMManager)TestExecuteObject;

            ItcIntegration IntegrationObject = TestExecuteManager.Integration;



            TestExecuteManager.Quit();



            Marshal.FinalReleaseComObject(IntegrationObject);

            Marshal.FinalReleaseComObject(TestExecuteManager);

            Marshal.FinalReleaseComObject(TestExecuteObject);



            IntegrationObject = null;

            TestExecuteManager = null;

            TestExecuteObject = null;

        }



Using this code, I can execute about 150 tests before the entire process crashes.  I get an exception saying the thread pool has run out, and the test run ends.  Memory usage by this point is over 1GB.



Am I doing something incorrectly?  It feels like something isn't getting released properly...  Thanks in advance!!!

  • Hi Charles,



    I created a sample application based on your code, but failed to reproduce the problem with a simple test project using TestExecute 8.60. It is possible that the problem is somehow related to your application or test project. Could you please send us your test project so we can try to recreate the problem with it? You can use the Contact Support form to submit the project.
     



    Also, please update TestExecute to version 8.60 and check whether the problem occurs in this case.