locked
Queued Components called from a Web Service

    問題

  • Hello All,

    I seem to be having a problem with COM+ that has me stumped.  I'm developing a Queued Component on an x64 Windows 7 box (but I've found the same issue on W2K8R2) with no success.  The component is (supposed to be) instatiated by a web service, but Marshal.GetActiveObject returns null.  I've combed through all the COM+ application settings and the Event Viewer with no luck. 

    Here is the code for the web service:

    using WCF = global::System.ServiceModel;

    namespace WCFService1.ServiceImplementation
    {
        using System;
        using System.Diagnostics;
        using System.Runtime.InteropServices;
        using Processor;
        using WCFService1.DataContracts;
        using WCFService1.MessageContracts;

        /// <summary>
        /// Service Class - Service1
        /// </summary>
        [WCF::ServiceBehavior(Name = "Service1",
            Namespace = "http://MSMQDemoR2.Model/2012/ServiceContractDsl1",
            InstanceContextMode = WCF::InstanceContextMode.PerSession,
            ConcurrencyMode = WCF::ConcurrencyMode.Single)]
        public abstract class Service1Base : ServiceContracts.IServiceContract1
        {
            #region ServiceContract1 Members

            public virtual MessageContracts.XsdMessage1 Operation1(MessageContracts.Message1 request)
            {
                return null;
            }

            #endregion ServiceContract1 Members
        }

        public partial class Service1 : Service1Base
        {
            public override MessageContracts.XsdMessage1 Operation1(MessageContracts.Message1 request)
            {
                var res = new XsdMessage1();
                var tRoot = new root() { ExtensionData = null, msg = "sent" };

                try
                {
                    var iQc = Marshal.GetActiveObject("queue:/new:{67F00E61-E75E-317E-BAE5-46C76A3F1C73}") as IQComponent;  // THIS RETURNS NULL

                    // iQc.DisplayMessage(messageToSend.Text);
                    Debug.Assert(iQc != null, "iQc != null");
                    iQc.ProcessQueue(msg: "test");
                    Marshal.ReleaseComObject(o: iQc);

                    tRoot.err = "good";
                }
                catch (Exception ex)
                {
                    tRoot.err = ex.ToString();
                }

                res.Root = tRoot;

                return res;
            }
        }
    }

    Here is the Queued COM Component:

    using System;
    using System.Data;
    using System.Diagnostics;
    using System.EnterpriseServices;
    using System.Messaging;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using Microsoft.Practices.EnterpriseLibrary.Data;
    using Microsoft.Practices.EnterpriseLibrary.Data.Sql;

    [assembly: ApplicationName(name: "QueueProcessor")]
    [assembly: AssemblyKeyFile(keyFile: "keyPair.snk")]
    [assembly: CLSCompliant(true)]
    [assembly: ApplicationActivation(ActivationOption.Server)]
    [assembly: ApplicationQueuing(Enabled = true, QueueListenerEnabled = true)]
    [assembly: ApplicationAccessControl(false)]

    namespace Processor
    {
        [ComVisible(true)]
        [CLSCompliant(true)]
        [InterfaceQueuing(Enabled = true)]
        public interface IQComponent
        {
            void ProcessQueue(string msg);
        }

        [ComVisible(true)]
        [CLSCompliant(true)]
        [InterfaceQueuing(Interface = "IQComponent")]
        public class MainClass1 : ServicedComponent, IQComponent
        {
            private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

            [ComVisible(true)]
            [CLSCompliant(true)]
            public void ProcessQueue(string msg)
            {
                Debug.Assert(Log != null, "log != null");

                Log.Info(message: "Application [ProcessQueue] Start");
                Log.Debug(message: string.Format(format: "msg:{0}", arg0: msg));

                string tres = string.Empty;

                try
                {
                    Log.Debug(message: "starting SQL run");
                    Database db = new SqlDatabase("Data Source=PCSOFFDGG;Initial Catalog=testdb;Integrated Security=True");
                    db.ExecuteNonQuery(CommandType.Text,
                                       "INSERT INTO results(st,name) SELECT a.st,b.name FROM people b INNER JOIN states AS a ON a.id=b.id");
                    using (var tdb = db.ExecuteReader(CommandType.Text, "SELECT * FROM results"))
                        while (tdb.Read())
                        {
                            tres += string.Format("{0}:{1}:{2}", tdb[0], tdb[1], tdb[2]);
                            Log.Debug(message: string.Format(format: "tres:{0}", arg0: tres));
                        }
                }
                catch (Exception ex)
                {
                    Log.Error(message: ex);
                }
                Log.Debug(message: "finished SQL run");

                Log.Debug(message: "starting MSMQ run");
                try
                {
                    using (var tMessageQueue = new MessageQueue(@".\private$\testa"))
                        tMessageQueue.Send(obj: tres);
                    Log.Debug(message: "MSMQ good");
                }
                catch (Exception ex)
                {
                    Log.Error(message: ex);
                }
                Log.Debug(message: "end MSMQ run");

                Log.Info("Application [ProcessQueue] End");
            }

            [CLSCompliant(isCompliant: true)]
            public MainClass1()
            {
                Log.Debug("Application [ProcessQueue] Constructor");
            }
        }
    }

    Thanks in advance for any ideas.

    Geoff

    2012年2月8日 下午 07:37

所有回覆


  • Just a quick follow up: I originally tried Marshal.BindToMoniker before trying Marshal.GetActiveObject

    Geoffrey J Gowey

    2012年2月8日 下午 08:32