none
Release COM+ object RRS feed

  • Question

  • I have COM+ server component written in C# that is consumed by a C# WPF client, All the COM components are registered on the Client machine, I am able to create an instance of COM component and call the methods but after i am done with i am not able to dispose it.

    COM+ class:

        using System;
        using System.EnterpriseServices;
        using System.Runtime.InteropServices;
        namespace Mdrx.PM.Server.Lookup.Svr
        {
            [EventTrackingEnabled(true)]
            [Guid("999999-A351-4AF9-AAFE-931549FD6EFA")]
            [ProgId("foo.PM.Server.Lookup.Svr.LkpQueryPat")]
            [Transaction(TransactionOption.Supported)]
            public class LkpQueryPat : ServicedComponent, IQuery
            {
                public LkpQueryPat();
                public int Query(dynamic vntToken, object vntIn, ref object vntData, ref int lngErrorID);

        }

    I have compile time reference to this assembly in my client project so i am able to directly instantiate an object. I try to use Marshal.ReleaseComObject but that throws exception:
    The object's type must be __ComObject or derived from __ComObject  

        LkpQueryPat patientLookupQuery = new LkpQueryPat();
        patientLookupQuery = null;

    On the server i can see under dcomcnfg that the object remains under In Call column and never goes away, even if i kill the client application.

    I noticed one more thing Objects column is the number of references client is holding and in my case it is 0 and that is because of these 2 lines, if i remove these then that number also keep increasing.

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms681593%28v=vs.85%29.aspx

    (patientLookupQuery as System.EnterpriseServices.ServicedComponent).Dispose();

    patientLookupQuery = null;

    What i don't understand is what the In Call column and how can bring that number to 0.

        
    • Edited by VikasMittal Monday, December 22, 2014 9:26 PM
    Monday, December 22, 2014 5:06 PM

All replies

  • Hello VikasMittal,

    >>I have compile time reference to this assembly in my client project so i am able to directly instantiate an object.

    I am wondering that you are actually not using COM but simply use a referenced .NET class since you mentions that you add a reference to this assembly.

    If so, the Marshal.ReleaseComObject(object) would throw this error since the object is not a COM+ object. And since it is recommended you write the assembly and add reference to these assemblies directly which is easier.

    If it is exact a COM+ server object, please have a try to use the Marshal.FinalReleaseComObject Method to see if it works.

    Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, December 23, 2014 3:36 AM
    Moderator
  • It has to be COM object because when I create the instance it actually creates the instance on the server (different machine).

    Also when i say Type.GetTypeFromCLISD the type is _comobject but when a create the instance using Activator it crates the actual instance (strongly typed instance).

    As i mentioned in my post i can use the Dispose and it kills the object but for some reason it still shows up in "In call" column in dcomcnfg

    Marshal.FinalReleaseComObject Method also throws the same error

    vikas

    Tuesday, December 23, 2014 1:52 PM
  • Hello vikas,

    It seems my suggestion isn’t work. Could you please provide a detail code of COM+ class? So that we could create an exact test to see why it throws this error and find a proper solution. Please also provided a description how you add the reference to the COM component and some code regarding the usage of COM+ component in you WPF client application.

    Thanks&Regards,

    Fred.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, December 24, 2014 3:37 AM
    Moderator
  • My class is very simple, It has all the typical COM realted attributes applied to the class and it has one public method:

    public interface IGetFeatureToggles
        {
            List<Data.FeatureToggle> GetAllFeatureToggles(object[] token);
           // List<Data.FeatureToggle> GetAllFeatureToggles(Token token);
        }
    
    


    /// <summary>
        /// Class for retrieving Feature Toggles
        /// </summary>
        [ProgId("Mdrx.PM.Server.FeatureToggle.Svr.GetFeatureToggles")]
        [Transaction(TransactionOption.Supported)]
        [EventTrackingEnabled(true)]
        [Guid("960D39FE-2792-44D7-AC2B-14CD7A1CB50F")]
        public class GetFeatureToggles : ServicedComponent, IGetFeatureToggles
        {
            #region private members
            #endregion
    
            #region constructors
            #endregion
    
            #region public properties
            #endregion
    
            #region public methods
    
            /// <summary>
            /// Retrieves all Feature Toggles
            /// </summary>
            /// <param name="token">Object Array representing a Token</param>
            /// <returns>List of FeatureToggle</returns>
            [AutoComplete]
            public List<Data.FeatureToggle> GetAllFeatureToggles(object[] token)
            {
                IGetDbFeatureToggleAll getData = new GetFeatureToggleAll();
    
                var properToken = new Token(token);
    
                var featureToggles = getData.GetFeatureToggleDataAll(properToken);
    
                if (featureToggles != null && featureToggles.Count > 0)
                {
                    var getUserAccess = new GetFeatureToggleUserAccessByFeatureToggleId();
    
                    foreach (var featureToggle in featureToggles)
                    {
                        featureToggle.UsersWithAccess = getUserAccess.GetUserAccessDataByFeatureToggleId(properToken, featureToggle.FeatureToggleID);
                    }
                }
                
                return featureToggles;
            }
    
            #endregion
    
            #region private methods
            #endregion
    
    
        }

    This class is registered on the client machine, I am adding a reference to the DLL, I need to the add the reference to my project because when i try to create an instance of the class using Activator.CreateInstance and the DLL is not there it gives in File not found exception.

    I am using this to get the type and create an instance;

    var iGetFeatureToggles = _comServerFactory.GetComServer<IGetFeatureToggles>(typeof(GetFeatureToggles));

    public T GetComServer<T>(string progId)
            {
                Type comType;
    
                if (ComClientAssembliesManager.IsClientType(progId))
                {
                    comType = Type.GetTypeFromProgID(progId, null);
                }
                else
                {
                    string remoteServer = ConfigurationManager.AppSettings[RemoteComputerNameConfigKey];
    
                    //TODO: Analyze how to call DCOM object with "localhost" remote server name.
                    comType = Type.GetTypeFromProgID(
                        progId, 
                        string.IsNullOrWhiteSpace(remoteServer) || remoteServer == "localhost"  ? null : remoteServer);
                }
    
                return (T)Activator.CreateInstance(comType);
            }


    Friday, December 26, 2014 11:58 PM
  • Hello VikasMittal,

    Thanks for providing detail infoamtion, for this issue, i a trying to invoke someone experiencedt to help look into it, it may take some time and as soon as we get any result, we will tell you.

    Thanks for your understanding.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Monday, December 29, 2014 5:53 AM
    Moderator
  • Hi Fred,

    Just checking if we found any solution for this.

    Thanks

    vikas

    Tuesday, January 6, 2015 1:42 PM
  • If you are still looking at it i have more information that might help. 

    As i mentioned before I am using COM+ services using ServicedComponent, I have 2 client a VB6 client and C# client.

    If i am using Vb6 client then i need to make a call to Dispose() in the server (Com+ service) code at the very end of the method client is calling, that makes sure that instances are released.

    If i am using C# the above method does not work, In this case the client has to call Dispose on the servicedComponent instance (the client has to call Dispose).

    So basically there are 2 different way to dispose based on the client, I need to find out a single way to do this.

    Vikas

    Friday, January 23, 2015 11:54 PM