Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Component Services / February 2006

Tip: Looking for answers? Try searching our database.

COM+ LC Event - Unable to invoke any of the subscribers

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Blair Allen Stark - 21 Feb 2006 13:49 GMT
[originally posted in framework.interop. . . refered here]

source: http://www.obj-tec.com/msdnforums/lcedemo2.zip

I am getting "An event was unable to invoke any of the subscribers (Exception
from HRESULT: 0x80040201)" on what appears to have been a properly subscribed
transient event.  

I have an Event Class in a signed library, LceEvent.dll, registered in COM+
via
           regsvcs LceEvent.dll

--------------------------------------------------------------------------------
Imports System.Runtime.InteropServices
Imports System.EnterpriseServices

<ComVisible(True)> _
Public Interface ITheEvent
   Sub Fire()
End Interface

<ComVisible(True), _
   EventClass()> _
Public Class TheEvent
   Inherits ServicedComponent
   Implements ITheEvent
   Public Sub Fire() Implements ITheEvent.Fire

   End Sub
End Class

--------------------------------------------------------------------------------
above class registers appropriately

I have a sink library, LceSink.dll with an Event Sink :

--------------------------------------------------------------------------------
Imports System.EnterpriseServices
Imports System.Runtime.InteropServices
Imports LceEvent

<ComVisible(True)> _
Public Class TheEventSink
   Implements ITheEvent
   Public Event Fired As EventHandler
   Private _subId As String
   Public Sub New()
   End Sub
   Public Sub Fire() Implements LceEvent.ITheEvent.Fire
       RaiseEvent Fired(Me, EventArgs.Empty)
   End Sub
End Class

--------------------------------------------------------------------------------

I have a helper class for transient subscriptions:

--------------------------------------------------------------------------------
Public Class LceHelper
   Public Shared Function CreateTransientSubscription( _
 ByVal clsid As String, ByVal subscriber As Object) As String
       Dim catalog As New COMAdmin.COMAdminCatalog
       Dim catalogCollection As COMAdmin.COMAdminCatalogCollection = _
           catalog.GetCollection("TransientSubscriptions")
       catalogCollection.Populate()
       Dim subscription As COMAdmin.ICatalogObject = catalogCollection.Add()
       subscription.Value("SubscriberInterface") = subscription
       subscription.Value("EventCLSID") = "{" & clsid & "}"
       subscription.Value("Name") = "TransientSubscription"
       catalogCollection.SaveChanges()                  
       ' POINT 1      
       Return subscription.Value("ID").ToString()
   End Function
   Public Shared Sub DeleteTransientSubscription(ByVal subid As String)
       Dim catalog As New COMAdmin.COMAdminCatalog
       Dim catalogCollection As COMAdmin.COMAdminCatalogCollection = _
           catalog.GetCollection("TransientSubscriptions")
       catalogCollection.Populate()
        ' POINT 5
        For i As Integer = 0 To catalogCollection.Count - 1
           Dim subscription As COMAdmin.COMAdminCatalogObject =
catalogCollection.Item( i )
           If subscription.Value("ID").ToString() = subid Then
               catalogCollection.Remove( i )
               Return
           End If
       Next
   End Sub
End Class

--------------------------------------------------------------------------------

I am trying to use in a form:

--------------------------------------------------------------------------------
Public Class Form1

   Private WithEvents _TheSink As LceSink.TheEventSink
   Private _thesub As String

   Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
       Dim t As Type
       t = Type.GetTypeFromProgID("LceEvent.TheEvent")
       _TheSink = New LceSink.TheEventSink()
       Try
           _thesub = LceSink.LceHelper.CreateTransientSubscription( _
                                                     t.GUID.ToString(),
_TheSink)
           ' POINT 2            
       Catch ex As Exception
           MessageBox.Show(ex.Message)
       End Try
       MyBase.OnLoad(e)
   End Sub

   Private Sub Button1_Click(ByVal sender As System.Object, _
                         ByVal e As System.EventArgs) Handles Button1.Click
       Dim evt As LceEvent.ITheEvent = New LceEvent.TheEvent
       Try
           ' POINT 3                
           evt.Fire()                
       Catch ex As Exception
           MessageBox.Show(ex.Message)
       End Try
   End Sub

   Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Disposed
       ' POINT 4        
       LceSink.LceHelper.DeleteTransientSubscription(_thesub)
   End Sub
End Class

--------------------------------------------------------------------------------

At POINT 1 (LceHelper.CreateTransientSubscription), catalogCollection.Count
has increased by 1

At POINT 2 (Form1 above), it appears the subscription succeeds as the call
to CreateTransientSubscription assigns a giud string to _subID

At POINT 3 (Form1 above), I get  exception An event was unable to invoke any
of the subscribers (Exception from HRESULT: 0x80040201)

At POINT 4 (Form1 above), trace into LceHelper.DeleteTransientSubscription

At POINT 5 (LceHelper.DeleteTransientSubscription )CatalogCollection.Count >
1, the subid is found and the subscription is released

What am i doing wrong? Why isnt the subscription being called?
Kevin Jackson - 22 Feb 2006 14:24 GMT
You do not use EventHandler nor RaiseEvent with COM+ LC Events

Here's some sample code we use for ours.  Sorry, it's in C++

THE INTERFACE AND PUBLISHER CLASS

#region ISNRWriteEvents

 /// <summary>

 /// Summary description for ISNRWriteEvents

 /// </summary>

 [GuidAttribute("115D79D5-6CB8-4954-ABAF-CB973A164629"), InterfaceQueuing]

 public interface ISNRWriteEvents

 {

   void SNRCreated(Guid EventTrackingGuid, QCObjectWrapper
PWSecurityIDWrapper, int SNRID, int PDOID, int PurchasedCRID, SqlInt32
SuppliedCRID, SqlInt32 ProgramID, bool IsLead);

   void SNRPurchasedCRIDChanged(Guid EventTrackingGuid, QCObjectWrapper
PWSecurityIDWrapper, int SNRID, int OldPurchasedCRID, int NewPurchasedCRID);

   void SNRSuppliedCRIDChanged(Guid EventTrackingGuid, QCObjectWrapper
PWSecurityIDWrapper, int SNRID, SqlInt32 OldSuppliedCRID, SqlInt32
NewSuppliedCRID);

   void SNRProgramChanged(Guid EventTrackingGuid, QCObjectWrapper
PWSecurityIDWrapper, int SNRID, SqlInt32 OldProgramID, SqlInt32
NewProgramID);

   void SNRLeadProgramSet(Guid EventTrackingGuid, QCObjectWrapper
PWSecurityIDWrapper, int SNRID);

   void SNRLeadProgramCleared(Guid EventTrackingGuid, QCObjectWrapper
PWSecurityIDWrapper, int SNRID);

   void SNRDeleted(Guid EventTrackingGuid, QCObjectWrapper
PWSecurityIDWrapper, int SNRID);

 }

 #endregion

 #region SNRWriteEvents

 /// <summary>

 /// Summary description for PDOWriteEvents

 /// </summary>

 [GuidAttribute("7BF8C3FF-F394-493a-BA53-4BD96FE04EE5"), EventClass]

 public class SNRWriteEvents : RequiredTransServicedComponent,
ISNRWriteEvents

 {

   public void SNRCreated(Guid EventTrackingGuid, QCObjectWrapper
PWSecurityIDWrapper, int SNRID, int PDOID, int PurchasedCRID, SqlInt32
SuppliedCRID, SqlInt32 ProgramID, bool IsLead){}

   public void SNRPurchasedCRIDChanged(Guid EventTrackingGuid,
QCObjectWrapper PWSecurityIDWrapper, int SNRID, int OldPurchasedCRID, int
NewPurchasedCRID) {}

   public void SNRSuppliedCRIDChanged(Guid EventTrackingGuid,
QCObjectWrapper PWSecurityIDWrapper, int SNRID, SqlInt32 OldSuppliedCRID,
SqlInt32 NewSuppliedCRID) {}

   public void SNRProgramChanged(Guid EventTrackingGuid, QCObjectWrapper
PWSecurityIDWrapper, int SNRID, SqlInt32 OldProgramID, SqlInt32
NewProgramID) {}

   public void SNRLeadProgramSet(Guid EventTrackingGuid, QCObjectWrapper
PWSecurityIDWrapper, int SNRID) {}

   public void SNRLeadProgramCleared(Guid EventTrackingGuid,
QCObjectWrapper PWSecurityIDWrapper, int SNRID) {}

   public void SNRDeleted(Guid EventTrackingGuid, QCObjectWrapper
PWSecurityIDWrapper, int SNRID) {}

 }

 #endregion

 #endregion

A SUBSCRIBER

 [GuidAttribute("964B7002-5873-4cee-8C58-493B1902E064")]

           public class CR_SNRWriteSink : RequiredTransServicedComponent,
ISNRWriteEvents

           {

                       #region ISNRWriteEvents Members

   #region SNRCreated

   public void SNRCreated(Guid EventTrackingGuid, QCObjectWrapper
PWSecurityIDWrapper, int SNRID, int PDOID, int PurchasedCRID, SqlInt32
SuppliedCRID, SqlInt32 ProgramID, bool IsLead)

   {

     PWSecurityID Identity;

     PropertyInstanceWrite WritePropertyInstance = null;

     try

     {

       // reconstitute the objects

       Identity = PWSecurityIDWrapper.Target as PWSecurityID;

       if (! IsLead)

         return;

       WritePropertyInstance = new PropertyInstanceWrite();

       WritePropertyInstance.SetMappings(Identity,

         PurchasedCRID,

         CommonDataTypes.ObjectType.CRCustomer,

         PDOID,

         new SqlInt32((int) CommonDataTypes.ObjectType.PDO),

         SNRID,

         CommonDataTypes.ObjectType.SNR,

         PDOID,

         new SqlInt32((int) CommonDataTypes.ObjectType.PDO),

         true);

       ContextUtil.SetComplete();

     }

     catch (Exception Ex)

     {

       ContextUtil.SetAbort();

       ExceptionManager.Publish(Ex);

     }

     finally

     {

       if (WritePropertyInstance != null) try {
WritePropertyInstance.Dispose(); }

                        catch{}

     }

   }

   #endregion

   #endregion

 }

FIRING THE EVENT

       WriteSNREvent = new SNRWriteEvents();

       WriteSNREvent.SNRCreated(Guid.NewGuid(), new
QCObjectWrapper(PWAdminUser), SNRID, PDOID, PurchasedCRID, SuppliedCRID,
ProgramID, bIsLead);

REGISTERING THE SUBSCRIBERS INTO COM+ PROGRAMMATICALLY - We do this in
Installer classes included in the subscriber assemblies by calling
InstallUtil from Visual Build (our build system)

   public static void RegisterComponentSubscriptions(string appName, string
componentName, string [] subscriberMethodNames, string interfaceGUID, string
eventCLSID, bool bQueued)

   {

     COMAdminCatalog oCatalog = new COMAdminCatalog();

     COMAdminCatalogCollection oApplications =
(COMAdminCatalogCollection)oCatalog.GetCollection("Applications");

     oApplications.Populate();

     foreach(COMAdminCatalogObject oApp in oApplications)

     {

       if (oApp.Name.ToString() == appName)

       {

         COMAdminCatalogCollection oComponents =
(COMAdminCatalogCollection)oApplications.GetCollection("Components",
oApp.Key);

         oComponents.Populate();

         foreach (COMAdminCatalogObject oComp in oComponents)

         {

           // replace component name with your subscriber component name

           if (oComp.Name.ToString() == componentName)

           {

             COMAdminCatalogCollection oSubscriptions =
(COMAdminCatalogCollection)oComponents.GetCollection("SubscriptionsForComponent",
oComp.Key);

             for (int SubscriberMethodIndex = 0; SubscriberMethodIndex <
subscriberMethodNames.GetLength(0); SubscriberMethodIndex++)

             {

               oSubscriptions.Populate();

               bool bExists = false;

               foreach (COMAdminCatalogObject oSub in oSubscriptions)

               {

                 // register each of your subscriptions if they are not
already registered

                 if (bExists = (oSub.Name.ToString() ==
subscriberMethodNames[SubscriberMethodIndex]))

                   break;

               }

               if (!bExists)

               {

                 COMAdminCatalogObject oSubscription =
(COMAdminCatalogObject) oSubscriptions.Add();

                 oSubscription.set_Value("Name",
subscriberMethodNames[SubscriberMethodIndex]);

                 oSubscription.set_Value("MethodName",
subscriberMethodNames[SubscriberMethodIndex]);

                 oSubscription.set_Value("Queued", bQueued);

                 // this is the GUID from the interface definition

                 oSubscription.set_Value("InterfaceID", interfaceGUID);

                 // this is the guid from the event class definition

                 oSubscription.set_Value("EventCLSID", eventCLSID);

                 oSubscriptions.SaveChanges();

               }

             }

             break;

           }

         }

         break;

       }

     }

   }

}

If you want to run your subscribers asyncronously, there's a little more you
need to do

E-mail me for more info.

Kevin

> [originally posted in framework.interop. . . refered here]
>
[quoted text clipped - 154 lines]
>
> What am i doing wrong? Why isnt the subscription being called?
Kevin Jackson - 22 Feb 2006 14:26 GMT
I mean c#. ;)

> You do not use EventHandler nor RaiseEvent with COM+ LC Events
>
[quoted text clipped - 469 lines]
>>
>> What am i doing wrong? Why isnt the subscription being called?
Blair Allen Stark - 23 Feb 2006 01:49 GMT
> > You do not use EventHandler nor RaiseEvent with COM+ LC Events

Yes i know you dont use events to sink the LCE.

TheEventSink is a wrapper that fires its own event when the LCE method is
called.

lets look a bit more closely -

TheEventSink has its own field "Fired" which is a .NET event delegate which
will notify the application that the LCE method was invoked.

<ComVisible(True)> _
Public Class TheEventSink
   Implements ITheEvent
   Private _subId As String

// EVENT BELONGING TO THE CLASS
   Public Event Fired As EventHandler

// LCE METHOD IMPLEMENTATION
   Public Sub Fire() Implements LceEvent.ITheEvent.Fire
// RAISE EVENT TO APPLICATION THAT 'Fire' was invoked
       RaiseEvent Fired(Me, EventArgs.Empty)
   End Sub
End Class
Blair Allen Stark - 23 Feb 2006 01:51 GMT
oh yeah, the impetus is that I only want one subscription per application.
the sink will notify other clients.
news.microsoft.com - 23 Feb 2006 05:32 GMT
It all works for us just dandy...  Even loosely couple events that use
queued components.

Good luck

>> > You do not use EventHandler nor RaiseEvent with COM+ LC Events
>
[quoted text clipped - 23 lines]
>    End Sub
> End Class
Blair Allen Stark - 23 Feb 2006 12:39 GMT
> It all works for us just dandy...  Even loosely couple events that use
> queued components.

are you saying my code works for you? or your code works for you???

what code works for you. . . Kevin Jacksons? I dont think thats a "transient
subscription", is it? thats a full fledged serviced component subscription
Kevin Jackson - 23 Feb 2006 20:56 GMT
My code works for me and yes we don't use transient subscriptions...  Full
blown component subscriptions...

>> It all works for us just dandy...  Even loosely couple events that use
>> queued components.
[quoted text clipped - 4 lines]
> "transient
> subscription", is it? thats a full fledged serviced component subscription
Blair Allen Stark - 23 Feb 2006 13:55 GMT
UGHHHH!!! I'm an idiot!!!

I found my problem

subscription.Value("SubscriberInterface") = subscription

should have been

subscription.Value("SubscriberInterface") = subscriber

frigging intellisense!!!

Yeah guys. ..  no need to make your subscriber a ServicedComponent

And my event firing is the proper pattern.
Kevin Jackson - 24 Feb 2006 02:26 GMT
It's always the little things ;)

> UGHHHH!!! I'm an idiot!!!
>
[quoted text clipped - 11 lines]
>
> And my event firing is the proper pattern.
Blair Allen Stark - 24 Feb 2006 05:08 GMT
well I am making progress. . .

Here is where I was going with this. . .
I want an ASP.NET application to fire the event. I want users to be able to
run an app and get a real-time view of certain activities.

whith these set in the COM+ Event Class assembly:
 <Assembly: ApplicationActivation(ActivationOption.Library)>  
 <Assembly: ApplicationAccessControl(Value:=False)>

I can get the event to fire between stand-alone windows applications. But
trying to fire from ASP.NET to windows app throws "unable to invoke any
subscribers"

But It doesnt fire from ASP.NET to windows app, or from windows to windows,  
when I have these assembly attributes set in the COM+ Event Class assembly:
<Assembly: ApplicationActivation(ActivationOption.Server)>
<Assembly: ApplicationAccessControl(Value:=False)>

Nothing happens - ASP.NET page works as expected, no event fired in Windows
app.

I have just in time activation set up on the COM+ Event Class class, too.

any ideas???

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.