1

I need to write a .NET6 library that allows some features only when it's used with a WinForms or WPF app (so no console app, no web service, etc...).

I already checked some other posts like this but hits like Environment.UserInteractive or System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle == IntPtr.Zero seem not to work.

Prerequisites are:

  • it must be cross-platform
  • it can't reference System.Windows.Forms or PresentationFramework
  • I can't use methods that import Windows library like [DllImport("kernel32.dll")]
  • I can't use a static method that is called by the application that uses my library

Listed below is the code I'm currently testing. It seems to work, but I'm wondering whether there is a more efficient and reliable way to reach my goal.

static bool? _isWindowsGuiApp = null;
    
static bool IsWindowsGuiApp()
{    
    if (!_isWindowsGuiApp.HasValue)
    {
        _isWindowsGuiApp = false;

        var entryAssembly = Assembly.GetEntryAssembly();

        if (entryAssembly != null)
        {
            string[] wpfAssemblies = { "PresentationFramework", "PresentationCore", "WindowsBase" };
            string[] winFormsAssemblies = { "System.Windows.Forms" };

            var referencedAssemblies = entryAssembly.GetReferencedAssemblies();

            foreach (var assemblyName in referencedAssemblies)
            {
                if (wpfAssemblies.Contains(assemblyName.Name))
                {
                    _isWindowsGuiApp = true; // WPF
                    break;
                }

                if (winFormsAssemblies.Contains(assemblyName.Name))
                {
                    _isWindowsGuiApp = true; // WinForms
                    break;
                }
            }
        }
    }

    return _isWindowsGuiApp.Value;
}
ilCosmico
  • 1,319
  • 15
  • 26
  • Why one dll? Why aren't you using wrappers or composition for added wpf or winforms functionality? If you put your winforms only functionality in a separate dll then you deliver that to a winforms app, but not to other apps. – Andy Feb 24 '23 at 08:42
  • *"it must be cross-platform"* - Obviously, your library is not cross-platform as it depends on OS (Windows) and framework (WPF, WinForms). Related code must not be part of the library if it should be platform independent. – BionicCode Feb 24 '23 at 08:57
  • In your posted code _isWindowsGuiApp is always true. – BionicCode Feb 24 '23 at 09:01
  • 1
    Iterating through the loaded assemblies is the correct solution. – Ali Reza Dehdar Feb 24 '23 at 09:34
  • 4
    Also a specific platform e.g. WPF can reference/load assemblies of other platforms e.g. WinForms. Iterating over loaded assemblies won't help. – BionicCode Feb 24 '23 at 09:37
  • @BionicCode no, _isWindowsGuiApp is not always true. It's invoked inside my assembly but it checks all the loaded assemblies of the project. You can try it creating a library with such a code and using that library in a WinForms/WPF app and you will see that it will return true. – ilCosmico Feb 24 '23 at 09:50
  • @AliRezaDehdar thanks for the feedback. Since it can be slow with projects that reference many assemblies, I'm wondering if there is a more efficient way to accomplish this. – ilCosmico Feb 24 '23 at 09:52
  • I thought you want to differentiate between WPF and WinForms too. All my statements are based on this assumption. But again, a platform independent library should not care about the platform it is executed on. – BionicCode Feb 24 '23 at 09:54
  • @Andy I don't neet to add wpf or winforms functionality, but my library must have different behavior according to what kind of app is using it. – ilCosmico Feb 24 '23 at 09:55
  • 2
    Then the library should simply be configured appropriately, e.g. by a static method that is called by the application. The referenced assemblies don't tell you whether the application actually uses them as you expect. Even a console application may reference PresentationFramework. – Clemens Feb 24 '23 at 10:03
  • @Clemens unfortunately, this is not an option in my scenario, but thanks for the hint. I'm going to edit my post by adding this prerequisite. – ilCosmico Feb 24 '23 at 10:05
  • @BionicCode that's true, also a specific platform e.g. WPF can reference/load assemblies of other platforms e.g. WinForms. That's why the solution I found does not satisfy me at all and that's why I opened this post :) – ilCosmico Feb 24 '23 at 10:08
  • 2
    There is no reliable way. The common solution is to design your libraries properly. That's why you *always* find dedicated libraries for each supported platform if they contain platform specific code. Instead of trying to produce an unreliable hack you should fix your library design. Again, a cross-platform library must be platform agnostic, if that makes sense to you. If this is not possible then extract the platform specific code and move it to a platform dedicated library. The client of your library knows what kind of application he is developing. – BionicCode Feb 24 '23 at 11:11
  • Obviously, you are writing a platform specific library (not cross-platform). – BionicCode Feb 24 '23 at 11:21
  • you could propably check if the app has a SynchronizationContext with (SynchronizationContext.Current != null) this might work for winforms and wpf. But as said more then once you should write diffrent libs for the target platforms. – jeb Feb 24 '23 at 11:44
  • I would be inclined to deliver a parent library which has platform agnostic code in it. Plus another library containing any platform specific code. Switch out that second one depending on usage. This is kind of how most apps do multi platform. If that doesn't suit then the next candidate I'd consider would be an environment variable. Rather than infer what it's running on, the lib could then explicitly check the environment variable. I think now it's clear what the question is, this is an opinion based question. – Andy Feb 24 '23 at 11:59
  • @jeb unfortunately, the SynchronizationContext.Current is null in a WinForms app till Form1 is instantiated. Moreover, it could be used in a console app as well, so I cannot use it for my goal, sorry. – ilCosmico Feb 24 '23 at 16:08

0 Answers0