Static event doesn't get subscribed in different dll - c#

I have one WinForms control project that produces a dll. There is a second dll project (also winforms control) that uses the first project. There is a third winforms project, this time a form, that uses the second project. So [Third Project] <>------> [Second Project] <>--------> [First Project]
The first project exposes a static event. I'm trying to subscribe to that event from the third project. The event stays as null (not subscriptions) after the += call.
Why is it not subscribing? Is it because the Winforms controls have their own thread? The FirstProject user control is created on the fly at some point in time. But I will expect the static to work correctly, without doing anything else,
Project 1
namespace Something
{
public partial class FirstClass : UserControl
{
...
public delegate void EventHandler();
public static event EventHandler MyEvent;
...
}
}
Project 3
namespace Another
{
public partial class ThirdClass : Form
{
...
public ThirdClass()
{
....
Something.FirstClass.MyEvent += new Something.FirstClass.EventHandler(MyHandler);
}
public void MyHandler()
{
}
...
}
}
EDIT
I have created a small application with the basics to get the three projects and the static event. And it works. Therefore something else is going on.
EDIT 2
The dll that contained the first project, the one with the event, was being loaded twice. I have just added an alias, but didn't help. And still will not explain when just after the += the event is still null.
EDIT 3 I transformed the event so I have the add/remove accessors pair. It does enter into the add. The Handler method gets the value correctly (and therefore no null), but once it goes outside, is null again.

The static event should work just fine. Try to debug your code to make sure the event registration is being called and that the event itself gets fired as expected. The event does not care about threads. It will accept the registration either way. Threading will, however, cause an exception if you try to edit the form on a thread besides the UI thread.

And the reason will be in my EDIT 2. Because is a static event, loading twice the dll (two different paths) was creating two different static events (or two different handlers). My EDIT 3 clearly showed that the event was being subscribed to.
Once I forced the third project (the one subscribing to the static event) to load the dll from the same location as the project creating the event (I didn't wanted to use the GAC), all worked.

Related

In Event Tracing for Windows (ETW), how do I use EventSource to point to Notepad and retrieve the menu item selected in an ETW Session?

I am trying to understand Event Tracing in Windows (ETW). What I want to do is capture which menu item was selected in Notepad. If I click Word Wrap, I want ETW to tell me this.
I have looked at the samples on GitHub. One of the Event Producers is the demo:
namespace TraceEventSamples
{
// In these demos, we generate events with System.Diagnostics.Tracing.EventSource and read them with ETWTraceEventSource
//
// Normally the EventSource and the ETWTraceEventSource would be indifferent processes, however, we
// don't do this here to make the scenario really easy to run. The code works in the multi-process case, however.
namespace Producer
{
[EventSource(Name = "Microsoft-Demos-SimpleMonitor")] // This is the name of my eventSource outside my program.
class MyEventSource : EventSource
{
// Notice that the bodies of the events follow a pattern: WriteEvent(ID, <args>) where
// ID is a unique ID starting at 1 and incrementing for each new event method. and
// <args> is every argument for the method.
// WriteEvent then takes care of all the details of actually writing out the values complete
// with the name of the event (method name) as well as the names and types of all the parameters.
public void MyFirstEvent(string MyName, int MyId) { WriteEvent(1, MyName, MyId); }
public void MySecondEvent(int MyId) { WriteEvent(2, MyId); }
public void Stop() { WriteEvent(3); }
// Typically you only create one EventSource and use it throughout your program. Thus a static field makes sense.
public static MyEventSource Log = new MyEventSource();
// You don't need to define this override, but it does show you when your eventSource gets commands, which
// is helpful for debugging (you know that your EventSource got the command.
protected override void OnEventCommand(EventCommandEventArgs command)
{
EventGenerator.Out.WriteLine("EventSource Gets command {0}", command.Command);
}
// We could add Keyword definitions so that you could turn on some events but not others
// but we don't do this here to keep it simple. Thus you either turn on all events or none.
}
This is creating events for the demo, but how can I wire this to Notepad instead? Can ETW be used for this type of logging, knowing what someone clicked on a menu of an application?
I have looked at various SO questions, but they did not help. One generic was, Is there a Microsoft (built-in) ETW Provider for tracing ETW lifecycle events?
I considered this because it does not require C#, C++ Event Tracing for Windows (ETW) wrapper but didn't understand how it helped me.
This makes me think I cannot do it with managed code if I didn't write the original program:
https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.tracing.eventsource?redirectedfrom=MSDN&view=netcore-3.1
What I am attempting to do is capture which menu item is selected, and take action with my program that caught the event. The reason for this is an old VB6 program. I cannot do what I need to do, so my last resort is to capture the menu item and get my application to do what I want. I wanted to start with a simple notepad.exe.
VB6 user clicks "View X." My C# application does "View Y".

Custom UserControl Won't show when fired by event in another project 'ClassLibrary'

I have two projects, one of them is my mainApplication and another is a classLibrary, where communicates with Hardware.
In the classLibrary I have an event, which is fired when x hardware is disconnected, on my mainApplication, I add that event to custom function, where
my custom control located on my mainApplication won't show up, but when call something like MessageBox, it shows ... Probably if I add that mainApplication to references on classLibrary it will work, but I don't want to do that.
Follow sample code
Class Library sat
public event ConnectedSATChanged connectionChanged;
MainApp
sat.connectionChanged += new
SAT.SATInternalFunctions.ConnectedSATChanged(Sat_connectionChanged);
private void Sat_connectionChanged()
{
MessageDialog.Show("WARNING"); // Wont show Or any other custom control
MessageBox.Show("Warning"); // Will Show ...
}
UPDATE
The follow code made it
var thread = new Thread(() =>
{
MessageDialog.Show("Warning!");
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Without adding reference you need to find a way to trigger an event in the class library. Either WCF, web server or database can be used here.

C# Custom EventHandler

i have a custom event handler in the page, and it is called by the user controls of it.
everything is fine, except there is error display in the code ( red highlighted), but the program can be compiled, and able to run with no apparent error.
but i want to fix (or understand) the reason why the visual studio showed error for that
the error is
the code is
-PAGE
Operator_agentcontrol2 agentcontrol = (Operator_agentcontrol2)Page.LoadControl("~/operator/agentcontrol2.ascx");
agentcontrol.displayLevel = (int)Common.WinLose_Level.lvChild4 + 10 + (Panel_agents.Controls.Count * 10);
agentcontrol.AppendProcess += Append_UC_Progress;//Error line
the event in the page-
public void Append_UC_Progress(object sender, EventArgs e)
{
Common.WinLose_ProgressStage wps = (Common.WinLose_ProgressStage)e;
progress.AppendProgress(wps);
SaveProgressVS();
}
-USER CONTROL
public partial class Operator_agentcontrol2 : System.Web.UI.UserControl
{
public event EventHandler<Common.WinLose_ProgressStage> AppendProcess;
}
Thanks
---Update---
I have tried to follow https://msdn.microsoft.com/en-us/library/db0etb8x(v=vs.85).aspx for the custom event handler.
but then i got this error
---Update---
Eventually I found that actually my scenario doesn't require to use something like EventHandler
i have changed the code in user control
public partial class Operator_agentcontrol2 : System.Web.UI.UserControl
{
public event EventHandler AppendProcess;
}
By doing this the error is gone, and the user control still able to call the Page's function successfully with an object Common.WinLose_ProgressStage.
As far as I can see, two errors are being reported...
1 - It cannot find a suitable overload for Append_UC_Progess (which takes a Common.WinLose_ProgressStage as an argument)
2 - The assembly containing Common.WinLose_ProgressStage is not referenced.
What I would suggest is happening, is that once it is all compiled the assembly containing Common.WinLose_ProgressStage gets pulled in (perhaps by another referenced assembly), and thus it is noticed that it inherits from EventArgs. It can therefore find a suitable overload of Append_UC_Progess and it all resolves ok.
In order to get rid of the error, I would suggest explicitly referencing the assembly containing Common.WinLose_ProgressStage, so that Visual Studio can see the inheritance tree at design time.

C# custom events doesn't want to work with forms, partial class

I'm creating an app, there is some class that does some background operations and after all is done, parent object is notified using event. To provide event functionality i use following code:
public delegate void ShopStateChangedEventHandler(object sender, QuantityManagerEventArgs ea);
public event ShopStateChangedEventHandler ShopStateChanged;
protected virtual void WhenShopStateChanged(QuantityManagerEventArgs ea)
{
if (ShopStateChanged != null)
{
ShopStateChanged(this, ea);
}
}
It was working fine in all cases while I was using this piece of code with classes I've made, today I needed to have some custom made event added to one of forms in my application. Unfortunately i'm getting build error saying that compiler was unable to find ShopStateChangedEventHandler in form that is parent to form with custom event, and error is about line that adds listener
qmgr.ShopStateChanged += new ShopStateChangedEventHandler(qmgr_ShopStateChanged);
I really have no clue where to look for source of this error while in all other classes where i use this code all works fine, i suspect is it either because fact that the class i try to add custom event inherits from Form or maybe because it is partial class. As for now im far in the woods if it comes to solving it and I have no idea how to crunch it.
I hope you could suggest me what to do, or how to alter my code to make it all work with form.
thanks in advance
mth
EDIT
error is CS2046
The type or namespace name 'type/namespace' could not be found (are you missing a using directive or an assembly reference?)
all classes and forms belong to the same namespace
and as for qmgr_ShopStateChanged for now its just empty method
void qmgr_ShopStateChanged(object sender, QuantityManagerEventArgs ea)
{
}
qmgr is instance of form that contains custom event code, qmgr and qmgr_ShopStateChanged along with code that creates listener and makes problem, belongs to main form of application (frmMain).
Declare your delegate directly on your namespace outside any class.

Having problem in understanding and creating events in WPF

I am new to WPF, and I am learning using the book Pro WPF C# 2010.
Now in the chapter about events, the book explains how to create events and register events in WPF and it gives, as an example, code from the ButtonBase class which is derived from some other class which the code doesn't mention clearly.
Now to understand the big picture, i have also tried to create my own simple class, and tried to register an event, which i'll try to raise later (just for my own understanding).
Here is the code I have written:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
namespace WPFRoutedEvents
{
public class EventTest
{
private string variable = "Event has occured";
public static readonly RoutedEvent myTestEvent;
//Constructor
public static EventTest()
{
EventTest.myTestEvent = EventManager.RegisterRoutedEvent("TestEvent", RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof(EventTest));
}
public string getVariable()
{
return this.variable;
}
public event RoutedEventHandler myTestEvent
{
add
{
//Here is the problem
// I cannot use base.AddHandler () because it does not exist
}
remove
{
//Here is the problem
// I cannot use base.RemoveHandler() because it does not exist
}
}
}// end of class EventTest
}
Now since this class has not been derived from any class, i cannot access the base class function AddHandler.
My questions are the following:
1) Which class has the original AddHandler function implemented from which i need to extend my class?
2) Someone please briefly explain the pipeline from writing and event to finally setting it up to the point where it'll call the handler when it occurs, i.e starting from implementing an event, event handler, registering an event, defining the syntax of the event handler (coding part), and the pipeline from when en event occurs to until it is handled (actual execution of an event and event handler). It'll add more to my understanding of the text.
3) What i find in the book is ClickEvent which has already been implemented somewhere, it is created, registered, and finally handled. What i want to know is how will a programmer register some new type of event which has not yet been implemented (example could be triple click, just for the sake of example, otherwise i know it exists), and then register that event and then design a handler.
4) Is there any type of events, or some other equivalent, that occur on a particular state of a data (some variable, resource etc) instead of some input device event? Like for example while dragging to draw a line, it reaches a particular length?
Thanks!
The RoutedEvent system is centered around the UIElement class and its AddHandler method.
You should only create routed events in classes that inherit UIElement.
All other classes should use ordinary CLR events.
When you register a routed event, UIElement will prepare to store handlers for the event in instances of your class.
When you call AddHandler, UIElement will add the handler to something like a Dictionary<RoutedEvent, Delegate>.
When you add an event handler in XAML, the generated MyFile.xaml.g.cs code will add the handler using the CLR event accessor.
When you call RaiseEvent, UIElement will loop through its dictionary and call each handler.
For more information about field-like and custom events in C#, see my blog.

Categories

Resources