0

I have a C# .NET app that makes calls into a 3rd party library. The app compiles and runs fine when the library is present, but halts on launch when it isn't.

The user has to install the referenced program separately from my program, so I would like to be able to warn the user that my program won't operate properly if the referenced program hasn't been installed.

I have tried checking the registry for the appropriate entries, and I have tried instantiating the reference object and making a simple method/property call inside a try/catch block, but these never get a chance to work, as Windows pops an exception when it tries to load the referenced library on program startup.

Is there any way I can catch this exception and warn the user nicely that the required program needs to be installed?

enter image description here enter image description here

TIA,

Frank

user3765883
  • 233
  • 1
  • 9
  • this construct should work: https://dotnetfiddle.net/3yWLME - you can’t use a try/catch in the same method – Rand Random Nov 12 '22 at 01:43
  • [Please do not upload images of code/data/errors.](//meta.stackoverflow.com/q/285551) – Ken White Nov 12 '22 at 01:57
  • Register your COM component https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/regsvr32 – T.S. Nov 12 '22 at 02:32
  • Does this answer your question? [How can I make something that catches all 'unhandled' exceptions in a WinForms application?](https://stackoverflow.com/questions/5762526/how-can-i-make-something-that-catches-all-unhandled-exceptions-in-a-winforms-a) – shingo Nov 12 '22 at 05:02
  • Thanks for the inputs so far. Not sure why Ken White's commented about uploading images of code, as neither of the images I uploaded contained code (one had an image of code COVERED UP by the Project Explorer window, but no code per se) – user3765883 Nov 12 '22 at 16:52

1 Answers1

0

So the answer, at least for my issue, was pretty simple once I really understood the problem. My C# .NET app crashed on load when a referenced library was missing. After looking through the above comments and doing some more reading, I discovered that .NET apps by default don't load reference libs until they are needed, so what was happening to me shouldn't be happening. After looking a little more closely at my code, I found this:

        //private BCObject bc = null; //11/12/22 assigning bc crashes when BC not installed
    private BCObject bc; //11/12/22 this doesn't, so can chk later in frmMain.Shown()

The commented-out line caused .NET to load the referenced dll, and when it failed, I got an unhandled exception. After some trial-and-error, I figured out that I could replace it with the uncommented line, which puts the 'bc' object at frmMain scope, but doesn't trigger a load because it's just a declaration, not a call. This allowed me to write the following in the frmMain.Shown() event:

        private void frmMain_Shown(object sender, EventArgs e)
    {
        //11/12/22 added dummy call to BC object to check for pgm install. Can't use registry to check

        bInitialized = true;
        UpdateControls();

        //string logstr = string.Format("Checking install status of Bridge Composer....", programDisplayName);
        //IsProgramInstalled("BridgeComposer");

        string logstr = string.Format("Checking Bridge Composer install status ....");

        try
        {
            if (bc == null)
            {
                bc = new BCObject(); //this will cause an exception if BC not installed
            }

            bc.Noui = true;
            logstr += "INSTALLED";
            AppendToLog(logstr, Color.Green);
            bBridgeComposerAvail = true;
        }
        catch (Exception)
        {
            logstr += "NOT INSTALLED! See https://bridgecomposer.com/Download.htm";
            AppendToLog(logstr, Color.Red);
            bBridgeComposerAvail = false;
        }
        if (chkFTP.CheckState == CheckState.Checked)
        {
            DoFtpUrlCheck();
        }

        //added 11/11/17
        if (chkEmail.CheckState == CheckState.Checked)
        {
            DoEmailListFileCheck();
        }

        //moved to bottom 11/11/17
        UpdateControls();
    }

Here I instantiate the declared 'bc'object using

 bc = new BCObject(); //this will cause an exception if BC not installed

And now this is where .NET attempts to load the library. If it exists, great. If it doesn't, then the exception gets handled properly - yay!

This approach also solved another problem, in that previously I had attempted to do this by checking for a registry entry. This works when the 32-bit version of the library is installed, because my app is 32-bit and thus the library registry entries are in the same registry hive that my app accesses by default. However, if the user installs the 64-bit version of the library, then by default my app can't see the registry entries, and thinks the library is missing even when it isn't. Moreover, my previous solution only worked when the registry key search succeeded, which makes it no solution at all.

.NET is happy to load either the 32-bit library or the 64-bit library and the change I made to delay the load operation into frmMain.Shown() works fine for either 'bitness' library.

user3765883
  • 233
  • 1
  • 9