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.