Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine whether a class is instantiated within a console application or wpf?

I need to write a wrapper around a third party api that peruses message pumps and hence needs to be handled very differently depending on whether the wrapper is instantiated on a UI thread (such as within a wpf application) or not (such as a console application).

If it does not run on a UI thread then I need a dispatcher and implement my own message pump.

For that purpose I need to know whether the wrapper is instantiated within a wpf application or not. It is not enough to determine whether the instantiation happens on a UI thread or not (as even in a wpf application the thread on which the wrapper is instantiated might not be the UI thread).

Is there any way I can figure out whether I am in a wpf or windows form environment with message pump or a console application where I have to implement my own message pump?

Thanks

like image 778
Matt Avatar asked Dec 18 '17 14:12

Matt


Video Answer


3 Answers

I think you might be best off to have three separate packages.

To make it auto-select, you would need to have references to both WPF and WinForms in your package. Assuming worstcase, your package just made me import both into my console application. Others might consider importing WinForms into an WPF application worst case and another group of people might do WinForms because they cannot access WPF (and therefor you just cut them of from using your package altogether).

like image 138
nvoigt Avatar answered Sep 19 '22 06:09

nvoigt


If no other answer satisfies your needs - you can use reflection to check if Application.Current is null or not, without directly referencing WPF assemblies (and the same works with WinForms):

private static bool IsWpfApplication() {
    var type = Type.GetType("System.Windows.Application, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
    if (type == null)
        return false;
    var currentProp = type.GetProperty("Current", BindingFlags.Public | BindingFlags.Static);
    if (currentProp == null)
        return false;
    return currentProp.GetValue(null, new object[0]) != null;
}

Note that this might load PresentationFramework dll into current app domain, even in console application. If that is a problem for you - you can do the same by inspecting assemblies already loaded in app domain:

private static bool IsWpfApplication2() {
    var wpfAsm = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(c => c.GetName().Name == "PresentationFramework"); 
    if (wpfAsm == null)
        return false;
    var type = wpfAsm.GetType("System.Windows.Application");
    if (type == null)
        return false;
    var currentProp = type.GetProperty("Current", BindingFlags.Public | BindingFlags.Static);
    if (currentProp == null)
        return false;
    return currentProp.GetValue(null, new object[0]) != null;
}
like image 34
Evk Avatar answered Sep 23 '22 06:09

Evk


Is there any way I can figure out whether I am in a wpf or windows form environment with message pump or a console application where I have to implement my own message pump?

You could check whether there is a top-level window available:

if (Process.GetCurrentProcess().MainWindowHandle != IntPtr.Zero)
    //WPF

MainWindowHandle should return a handle provided that the WPF application has a main window.

You should also be able to use the native GetConsoleWindow function to determine whether you're in the context of a console application.

like image 21
mm8 Avatar answered Sep 21 '22 06:09

mm8