Events of .net class not raised in second appdomain - c#

Following Situation: A .Net4 WPF application is creating multiple appdomains on startup, launching the mainwindow in the first custom created appdomain, simulating a multiple instance behavior inside a single process, e.g. I´m able to start a second, third,... mainwindow where each will run in its own appdomain isolated from the others (lessons learned, that doesn´t affect native components)
AppDomain appDomain = AppDomain.CreateDomain("FancyAppDomainIdentifier");
appDomain.DoCallBack(() =>
{
var thread = new Thread(OnThreadStart);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
});
Where OnThreadStart() is basically doing a
new App().Run();
where App is the Standard System.Windows.Application.
This has been working nicely so far, but now I have a third party component which is basically a .net wrapper for some com components interacting with some hardware. The wrapper component is raising events to relay hardware events (button pressed) but these events are not raised, if I register the eventhandler in the first custom created appdomain.
If I remove the [STAThread] attribute from the method responsible for creating the custom appdomains, making the first custom created appdomain the first thread running STA, the events get raised.
I´ve had issues with native components when running multiple windows using this setup, but since this is currently only one window and only one instance of the wrapper I´m stuck.

Related

Self-updating WPF application, launcher process load WPF app via reflection

In a Winforms application, we have developed a self updating application launcher and I'm trying to mimic the same with WPF but am facing some issues. The way this worked with Winforms:
Launcher process (with not reference to main application) will check for newer libraries and download as necessary
Launcher will then load the assembly (Assembly.Load) from an STA Thread and then via reflection, call an Init method in that assembly (that performs a bunch of init logic while the launcher is acting as a splash screen and displaying progress)
After Init is complete, Laucher will call a Handoff method via reflection in the loaded assembly which will create a new ApplicationContext with the new MainForm and then call Application.Run(newAppContext).
Launcher will close its Window
I'm trying to mimic the same in WPF but the issues I'm having:
There doesn't appear to be the concept of ApplicationContext that I could transfer the MainForm to
I'm not sure how to handle App.xaml/resources since I can't put a "second" App.xaml in the application dll, so I'm not sure how to handle loading of resources/styles
When I Show a new MainWindow in the "Handoff" call that is called via reflection, the window opens briefly but then disappears
Appreciate any guidance on how I can implement the desired behavior in a Wpf application.
WPF apps derive from a base class of System.Windows.Application. The basic template that VS uses creates a App.xaml and App.xaml.cs. This class has an static entry point of
public static void Main()
This is what I use:
var type = yourloadedassembly.GetType( "YourNamespace.App" );
type.InvokeMember( "Main", BindingFlags::Public | BindingFlags::Static | BindingFlags::InvokeMethod, null, null, null );
For anyone interesting, solving this was actually quite trivial:
Create a Wpf Application (the launcher)
Create an "Application" assembly (can be a dll) that hosts the entry point for your application specific code
Have the launcher load the application assembly dynamically (Assembly.Load)
In your application assembly, have some static entry point that can be called via reflection from the launcher.
When the launcher calls the entry point method via reflection, add your resources and new a MainWindow from the application assembly to assign to Application.Current.MainWindow:
Application.Current.Resources = new ResourceDictionary() {Source = new Uri("pack://application:,,,/MyApp.UI.Styling;component/Common.xaml")};
Application.Current.MainWindow = new MainWindow();
Application.Current.MainWindow.Show();
Back in the Launcher, Close() the Launcher window

Windows application and message from asynchronous request

I have developed a class library (former console application). I want to build a windows forms application arround it to do different kind of actions with the application. For example to pass different values of a startup parameter to the class library.
The class library has a lot of console messages and an error object containing all kind of errors.
On the windows forms application I put 2 textboxes. My goal is to output the console messages to the first textbox (txtMessages) and the errormessages to the second textbox (txtErrorMessages).
The windows application will start the process in the class library as a new thread so it's asynchronous which will cause the windows forms application to instant refresh the textboxes
How can I achieve this?
You can e.g. expose 2 events from your library's class:
public event Action<string> outputMessage;
public event Action<string> errorMessage;
In the library, instead of writing to console you raise those messages. Then in the GUI part you subscribe for that 2 messages, and update your textboxes.
Don't forget you need to marshal the events to your GUI thread to update your controls. I think it'll be easier in the GUI part of the app. To do that, you can use any method from here in your event handlers.

How to call code to be run on specific worker thread from Windows Phone 8 UI thread?

My application is derived from a Windows Phone 8 Direct3D Xaml sample, where a C# program instantiates a WinPRT component that contains a Direct3D device. The C# code runs on the UI thread and the component code runs on a separate application thread. The WinPRT component works with a C++ pre-compiled library that contains variables declared per-thread, static __declspec(thread).
The variables get initialized when needed in the application thread, but the shutdown (caused by the lifecycle Closing event) is called on the UI thread. The shutdown process uses the wrong set of per-thread variables which haven't been initialized and causes a crash.
I haven't found any method on the WinPRT component that gets called on the application thread during shutdown. I was hoping to find one to hook my stuff into but there doesn't seem to be any.
So, how do I call the shutdown code to be run on the application thread from the UI thread?
WinPRT severely limits the threading functionality available to me. I haven't been able to find a workable solution. I looked at the Dispatcher class, but on WinPRT it's only used to run code on the UI thread from a worker thread and not vice versa. What other options might there be?

Getting list of all windows in current thread

I am starting a new UI-Thread in my WPF-application. Now I am searching a way to get a list with all windows in this thread - like I will get it for the main-thread with System.Windows.Application.Current.Windows.
Is there something in the .NET-Framework or does I have to implement it myself? When I have to implement it myself, perhaps someone have little bit of sample-code?
To quote MSDN:
A Window reference is automatically added to Windows as soon as a window is instantiated on the user interface (UI) thread; windows that are created by worker threads are not added. A Window reference is automatically removed after its Closing event has been handled and before its Closed event is raised.
By default, the first item added to the Windows property becomes the MainWindow.
This property is available only from the thread that created the Application object.
So it seems the windows created by worker threads are not hold in any collection automatically. I assume you create that window on the worker thread - so you should store a reference to it yourself for later access (you could do that in the Windows constructor by adding this to some window manager class)

System.Windows.Forms.Timer object does not tick when loaded from an activated assembly (plugin)

I am currently working on a project that loads assemblies (plugins) into the primary AppDomain space (via Reflection's Assembly.LoadFile() and the Activator class). As a part of the API with the plugins, the hosting application can request a Control-derived object to display on the host's form.
Essentially: the "hosting application" is a WinForms application that can load assemblies that contain controls. The hosting application loads the assemblies (via Assembly.LoadFile()) and then asks for a control from each assembly. The control is then rendered (added to a container) on the form.
Everything appears to work fine (buttons, labels, images, etc.) with the control and it IS interactive. However, if a Timer (WinForms component - NOT System.Threading.Timer) is used in the form - it does NOT tick. If the control is used directly in the host (when referenced as a dependency), the timer will tick as expected.
Is anyone aware of problems with WinForms Timer not being able to properly hook into the message pump if loaded from an assembly?
It isn't clear what "AppDomain space" might mean. Guessing: here's an excellent blog post that describes the hazards of loading controls in a secondary AppDomain. The key part is this one, followed by advice on how to make it work:
Windows Forms only supports isolating
top-level windows via app domains. It
does not support parent-child
relationships across domains. Many
people have assumed that because
Control ultimately derives from
MarshalByRefObject that it can
successfully be remoted; this is not
true. Certain interfaces on a control
can be remoted across domains, but the
control’s API itself does not support
remoting. When you see exceptions
stating that the object cannot be
remoted because it isn’t serializable,
what you’re seeing is that someone has
tried to cast the remote proxy to
Control.

Categories

Resources