C# .NET app launch exception when referenced library is missing - c#

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?
TIA,
Frank

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.

Related

RJCP.IO.Ports SerialPortsStream System.IO.IOException - Invalid configuration (BreakState, Length, Position)

I am currently working on a simple WPF application for serial data acquisition from an Arduino Mega Board (for testing purposes at this time, to be scaled to other serial devices).
Environment and packages:
Target Framework: .NET Framework 4.8, Visual Studio 2019
SerialPortStream (by Jason Curl - RJCP) version: 2.3.1
Please note that I recently started playing around with C# and I am more familiar with C++ ;)
My app searches and fills the serial ports present in my PC on a ListBox upon loading, then I must select the desired port from the ListBox and open it with a Button. Its callback configures the SerialPortStream object.
After successfully selecting the port, as seen in the console image below, the following exception is thrown to the console and the app just hangs:
Therefore, I decided to insert a breakpoint at the beginning of my code, to inspect my USBPort object, and the object shows errors in the Length, Static Members and Position properties. Inspecting the same object (USBPort) in the method where is configured shows the same errors
A short snippet of my main application code is the following (the lines marked with (*) represent my inserted breakpoints for debugging):
using RJCP.IO.Ports;
using System;
// ... and others
myApp{
public partial class MainWindow: Window {
private string ComPortName;
private int BaudRate;
private SerialPortStream USBPort = new SerialPortStream();
// ... plus other declarations
public MainWindow(){
InitializeComponent();
(*) BaudRate = 115200; // Inserted a breakpoint here to inspect USBPort in the debugger
}
// Start communication Callback/Binding --> Connect button Click binding
private void StartCOM_Click(object sender, RoutedEventArgs e){
try{
(*) USBPort = new SerialPortStream(ComPortName, BaudRate);
USBPort.Open(); // Inserting a breakpoint here shows the same errors in the watch window
// ...subsequent actions
} catch(Exception ex){
if(ex is IOException){
throw new IOException("Unable to create serial port"); // Message does NOT get displayed
}
}
}
Please note that my approach USED to work just fine and I was able to read lines from the serial port. Something broke after I refactored some parts of my code NOT related to the SerialPortStream object. I even tried with an old version of my code and now it keeps throwing the same error every time.
Is my way of pre-declaring my USBPort object using the empty constructor, then configuring it inside the callback correct?
What is the "specified method" that the Length property refers to?
Does the RJCP dll strongly depend on the framework used? According to the GitHub repo, it should work fine in 4.8.
Are different Windows 10 versions related to this issue? My code worked fine yesterday on my laptop at work and it doesn't on my Home's PC. (At the moment I have no access to that laptop).
Should I fall back to previous versions of the RJCP package?
Thank you, guys
Going over your individual questions:
Is my way of pre-declaring my USBPort object using the empty constructor, then configuring it inside the callback correct?
Yes. This is fine. They're just properties until the port is Open()ed.
But your code snippet you provide ignores this, because in StartCOM_Click you instantiate a new instance of SerialPortStream anyway. Check that you haven't opened the same port twice, which may lead to a resource conflict (Windows doesn't allow opening the same serial port from one or more applications more than once).
What is the "specified method" that the Length property refers to?
The Length and Position property are not defined, that the CanSeek property is false in this particular implementation.
Does the RJCP dll strongly depend on the framework used? According to the GitHub repo, it should work fine in 4.8.
Using package 2.3.1 has libraries for .NET 4.0, .NET 4.5 and .NET Standard 1.5. The NuGet package manager should be choosing the .NET 4.5 compiled version when running on top of .NET 4.8 which is described by Supporting Multiple Target Frameworks.
you can confirm this by checking the library RJCP.SerialPortStream.dll that is given next to your compiled program. Just check the sizes. The .NET 4.5 version is 233kB, the .NET Standard version is 246kB.
You probably know that the runtime itself, if you have .NET 4.8 installed, is a high compatibility in place upgrade for all other versions. So software targetting .NET 4.5 or .NET 4.8 runs essentially the same code underneath (I say essentially, because MS does have some compatibility checks, but they aren't relevant here).
Are different Windows 10 versions related to this issue? My code worked fine yesterday on my laptop at work and it doesn't on my Home's PC. (At the moment I have no access to that laptop).
It's more likely that this is related to the driver itself, not liking something in particular. Unfortunately, from the description given, it's difficult to tell what. To debug this, it's best to track in the GitHub issue.
Should I fall back to previous versions of the RJCP package?
There has been a few bugfixes, etc. but nothing described here that suggests this would make a difference.

Microsoft Agent "was unable to start"

I followed an old tutorial for using MS Agent with C#, and i'm not going to use an alternative to it, I specifically want to use MS Agent.
I added a refrence to the COM object Microsoft Agent Control 2.0 in refrences (and had to fix some code to have proper syntax again).
I'm using Windows 10, but that isn't an issue, MASH, for example, works fine.
If I build it for x86, I get the following error:
Building for x64 tells me it isn't registered (makes sense):
Here's my code:
public partial class Form1 : Form
{
private AgentObjects.Agent Agent1;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
Agent1 = new AgentObjects.Agent();
Agent1.Characters.Load("Ralsei", "Ralsei.acs");
var ralsei = Agent1.Characters["Ralsei"];
ralsei.Show();
}
catch (Exception ex)
{
MessageBox.Show("Can't use MS Agent.\n"+ex.ToString());
}
}
}
As you can see, the only event Form1 has is Load, so I didn't bother adding the Design.cs.
Update 1: This problem actually seems to NOT have to do with running Windows 10, like I thought it might have. Building this for .NET 4 and running it on XP shows the same error.
Update 2: I decided to mess around with VBScript, which works fine with similar code????
Update 3: I thought hmm, maybe VBScript does this differently than I am in C#, and decided to try using an ActiveX Object.
Literally the same error, thank you C# very cool
If you have Windows 10 64-bit, you could install free TTS program Claude to fix the error 0x800400154.
Also, keep in mind, what if your C# project targets x86, when you must add reference to "C:\Windows\MSAgent64\AgentCtl.dll" and if your C# project targets x64, when you must add reference to "C:\Windows\MSAgent\AgentCtl.dll".
Unfortunately, according to Introduction to Microsoft Agent, it seems that:
[Microsoft Agent is deprecated as of Windows 7, and may be unavailable in subsequent versions of Windows.]
And that's probably why your getting the Agent was unable to start error message.
Regarding the more cryptic message, it's probably because you don't have an x64 version of the COM library installed in your Registry (which won't help you even if you did have it, as the service is deprecated).
Hope it helps!

What is causing my release build to crash (XNA)?

I've recently made a release build of a demo game. I've tested it on all my machines at home, a combination of Windows 7 and Windows 8 machines, all 64 bit operating systems.
I passed the demo to a friend who said it is crashing on his machine.
I've built the game as an x86 release so it should work in most Windows environments. As a test I loaded it up here at work and it also fails. I'm combing logs to try and work out why it is failing but don't quite understand the issue if someone could have a look for me.
According to the registry I do have a version of .NET 4.5.1 installed which is good. My .NET crash log provides the following error.
Application: Monochromia.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.IO.FileNotFoundException Stack: at Monochromia.Program.Main(System.String[])
I've had a look at my main Method (which again works on other machines) and it looks as follows:
using System;
namespace Monochromia {
#if WINDOWS || XBOX
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
using (Game1 game = new Game1())
{
game.Run();
}
}
}
#endif
}
Is there anywhere I can go to find out specifically which file is missing? So I can try and work out why it is breaking. As a I said this is working fine on about 4-5 other machines I have run it on and I imagine there is a common element missing on other machines but I am not sure where to start looking to find out the missing element.
If it helps here is an actual crash log from the game:
Version=1
EventType=APPCRASH
EventTime=130597875140383880
ReportType=2
Consent=1
ReportIdentifier=91cf3b49-6606-11e4-93c4-c8600067af2a
IntegratorReportIdentifier=91cf3b48-6606-11e4-93c4-c8600067af2a
WOW64=1
Response.type=4
Sig[0].Name=Application Name
Sig[0].Value=Monochromia.exe
Sig[1].Name=Application Version
Sig[1].Value=1.0.0.0
Sig[2].Name=Application Timestamp
Sig[2].Value=5459faaf
Sig[3].Name=Fault Module Name
Sig[3].Value=KERNELBASE.dll
Sig[4].Name=Fault Module Version
Sig[4].Value=6.1.7601.18409
Sig[5].Name=Fault Module Timestamp
Sig[5].Value=53159a86
Sig[6].Name=Exception Code
Sig[6].Value=e0434352
Sig[7].Name=Exception Offset
Sig[7].Value=0000c42d
DynamicSig[1].Name=OS Version
DynamicSig[1].Value=6.1.7601.2.1.0.768.3
DynamicSig[2].Name=Locale ID
DynamicSig[2].Value=3081
DynamicSig[22].Name=Additional Information 1
DynamicSig[22].Value=0a9e
DynamicSig[23].Name=Additional Information 2
DynamicSig[23].Value=0a9e372d3b4ad19135b953a78882e789
DynamicSig[24].Name=Additional Information 3
DynamicSig[24].Value=0a9e
DynamicSig[25].Name=Additional Information 4
DynamicSig[25].Value=0a9e372d3b4ad19135b953a78882e789
UI[2]=C:\Users\Admin1\Downloads\Release\Monochromia.exe
UI[3]=Monochromia has stopped working
UI[4]=Windows can check online for a solution to the problem.
UI[5]=Check online for a solution and close the program
UI[6]=Check online for a solution later and close the program
UI[7]=Close the program
LoadedModule[0]=C:\Users\Admin1\Downloads\Release\Monochromia.exe
LoadedModule[1]=C:\Windows\SysWOW64\ntdll.dll
LoadedModule[2]=C:\Windows\SYSTEM32\MSCOREE.DLL
LoadedModule[3]=C:\Windows\syswow64\KERNEL32.dll
LoadedModule[4]=C:\Windows\syswow64\KERNELBASE.dll
LoadedModule[5]=C:\Windows\syswow64\ADVAPI32.dll
LoadedModule[6]=C:\Windows\syswow64\msvcrt.dll
LoadedModule[7]=C:\Windows\SysWOW64\sechost.dll
LoadedModule[8]=C:\Windows\syswow64\RPCRT4.dll
LoadedModule[9]=C:\Windows\syswow64\SspiCli.dll
LoadedModule[10]=C:\Windows\syswow64\CRYPTBASE.dll
LoadedModule[11]=C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll
LoadedModule[12]=C:\Windows\syswow64\SHLWAPI.dll
LoadedModule[13]=C:\Windows\syswow64\GDI32.dll
LoadedModule[14]=C:\Windows\syswow64\USER32.dll
LoadedModule[15]=C:\Windows\syswow64\LPK.dll
LoadedModule[16]=C:\Windows\syswow64\USP10.dll
LoadedModule[17]=C:\Windows\system32\IMM32.DLL
LoadedModule[18]=C:\Windows\syswow64\MSCTF.dll
LoadedModule[19]=C:\PROGRA~2\KASPER~1\KASPER~1\mzvkbd3.dll
LoadedModule[20]=C:\PROGRA~2\KASPER~1\KASPER~1\sbhook.dll
LoadedModule[21]=C:\Windows\syswow64\ole32.dll
LoadedModule[22]=C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
LoadedModule[23]=C:\Windows\system32\MSVCR110_CLR0400.dll
LoadedModule[24]=C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\ce5f61c5754789df97be8dc991c47d07\mscorlib.ni.dll
LoadedModule[25]=C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll
LoadedModule[26]=C:\Windows\syswow64\OLEAUT32.dll
LoadedModule[27]=C:\Windows\Microsoft.NET\Framework\v4.0.30319\diasymreader.dll
FriendlyEventName=Stopped working
ConsentKey=APPCRASH
AppName=Monochromia
AppPath=C:\Users\Admin1\Downloads\Release\Monochromia.exe
It seems my issue was that the target system although having the .NET Framework did not contain the XNA Framework from http://www.microsoft.com/en-us/download/confirmation.aspx?id=27598. The reason that I picked this up was that I was looking at other bug reports from other games and noticed people having issues with Terraria which was made with XNA. It made me realise the other target machines I had tested earlier had played Terraria at some point and thus would have had the XNA Framework installed when the game was first run.
I may have to look at bundling this in an installer or doing a check for the Framework first. Problem solved!
The code causing this exception is most likely linked to the disposal of the game object. Note that using an object calls IDispose.Dispose() after the using block, which would explain why this happens during shutdown. This should go away if you wrap the using statement in a try-catch block, but it may not help diagnose the problem.
For diagnosis, I would recommend debugging on the target machine so you can get the full stack trace of the exception, and barring that, make a release Console build, and wrap the using in a try-catch as above, but slam the Exception.StackTrace into the console window for viewing.
try
{
using (Game1 game = new Game1())
{
game.Run();
}
}
catch(Exception E)
{
Console.WriteLine(e.StackTrace);
}
Note that it might also be helpful to give your tester a debug build so that the stack trace or other exception data isn't optimized away.

Debugging Help: Wrapped c++ DLL running fine in one application, crashing another

I'm migrating some C# Demo Code from a Command Window Application to an WPF Application. The Demo Code is accessing a wrapped unmanaged C++ Library. The library is provided by a third party, so I don't have access to the code.
While the Demo Code is running fine, the exact same code crashes in my WPF application after a while. The library is accessed, some configuration files are loaded but when I'm calling a certain method my application is throwing an error (I had to enable "Unmanaged Code Debuggin" to see it):
First-chance exception at 0x7726c41f in Application.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x279ce1b4..
SCAPE exception caught: bad allocation
This is the part where the error is thrown:
unsafe
{
fixed (S_DATA* pim = &_im)
{
bool success = false;
try
{
success = RunAnalytics(_im); // <--- returns false, error message in debugger
}
catch (Exception ex)
{
throw new ScrException("ERROR: Unmanaged exception", ex);
}
}
}
Both applications are running on ".NET Framework 4.0 Client Profile".
Any hints how to proceed from here on? I'm out of ideas...
Edit:
I spent the last days setting up different scenarios trying to figure out, what's the source for the issue.
Original WPF in Original Solution > fails
Original WPF in Dummy Solution > works
Dummy CMD in Original Solution > works
Dummy CMD in Dummy Solution > works
Minimal WPF in Dummy Solution > works
Minimal WPF in Original Solution > works
I'm not really any wiser...
Edit 2: After a long, long time I figured it out - a post-build script interfered with some local resources that were copied on top of one another, so I was using an outdated configuration file with some new settings... not a very satisfying solution.

Using R(D)COM for integrating R with C#

I am trying to use R(D)Com interface. I have R 2.12.1 installed on machine. For using this interface in C#, I loaded rscproxy_1.3-1 package and then installed R_Scilab_DCOM3.0-1B5 on my machine. Also, I copied sciproxy.dll from Program Files\R(D)COM Server\Scilab to Program Files\R(D)COM Server\bin, as informed while installing the interface.
My Problem:
As a part of testing, I tried the code from blog post http://vvella.blogspot.com/2010/08/integrate-c-net-and-r-taking-best-of.html. But my form application failed due to exception raised by statement rconn.Init(“R”). The exception text was Exception from HRESULT: 0x80040013 I tried to run samples from Programs->R->R(D)COM Server->Server 01 Basic Test. On launched form, I clicked button “Start R” but it failed with error printed in text box as “Initializing R...Function call failed Code: -2147221485 Text: installation problem: unable to load connector”
I tried this:
I tried to troubleshoot it with the help of Index html page, and there under installation section, I found that there must be rproxy.dll under installed R/Bin folder. Also, HKEY_LOCAL_MACHINE\Software\R-core\R\InstallPath should point to installation folder.
Things lacking on my machine are
the installed R/bin folder doesn’t
contain rproxy.dll. Where can I get
this dll? Or is it sciproxy.dll
instead?
HKEY_LOCAL_MACHINE\Software\R-core\R\InstallPath
points to installation folder, but
there is no entry under
HKEY_CURRENT_USER\Software.
I can guess there is something fishy about installation, or registering COM server. But I am not successful in figuring it out.
Could you please tell me where am I going wrong?
thanks,
Kapil
Oh god I remember this being a huge pain in the arse. Lets see if I can remember... And before I start, I warn you that I just "got this working" and never cared to work out if I could remove parts from the process.
Downloads are available from http://rcom.univie.ac.at/download.html . If I remember correctly, the RandFriends package is all you need, it installs a crapload (just install it all) but is simple. Alternatively, I think if you install the 'rscproxy' package in R you can just download the 'statconnDCOM' and install that. Memory is hazy, but I know one of these methods results in an annoying splash screen everytime you run your C# executable, and one doesn't. Although that could have just been some setting I played with.
Now, I can't remember how you verify that stuff has installed successfully. Pretty sure it comes with examples though. Once that is started, get your C# project open. Reference the following projects,
StatConnectorCommonLib
STATCONNECTORSRVLib
In your code, you will probably want to implement a IStatConnectorCharacterDevice so you get the R output coming back out in C#. Your code to initialise will then look something like,
private StatConnector _StatConn;
private IStatConnectorCharacterDevice _CharDevice;
private Whatever()
{
// declare
_StatConn = new StatConnectorClass();
_CharDevice = new MyCharDevice();
// init R, wire up char device
_StatConn.Init("R");
_StatConn.SetCharacterOutputDevice(_CharDevice);
}
Then you should be able to just use the functions as needed
_StatConn.EvaluateNoReturn("x <- 3");
var returnObj = _StatConn.Evalute("1 + 1");
Hope that helps.
tl;dr download RAndFriends, do fresh install with that
I had a similar problem calling R.Init(), I found R.GetErrorText() returns the actual error message

Categories

Resources