I know that I can open a DLL file with an assembly browser, such as ILSpy, to see the classes and methods that it contains. But if a process is currently using a DLL, is it possible to know what method it is currently using? And any other details, such as the exact line that it is on, and if it threw an exception?
This question isn't language specific, but I'm most interested in doing this in C#. And the DLLs are compiled in the .NET framework.
My goal is to build a logger that shows what part of my code a process is using, and if it threw an exception, which function it came from.
The closest I know how to get to this is to check the callstack of a process. It is easy to do this using ProcessExplorer (get it here: https://technet.microsoft.com/en-gb/sysinternals/bb896653.aspx)
Then:
Open Process Explorer, select the process you need more information
about, then right click > Properties...
Select the 'Threads' tab. This will open up the list of all threads for this process.
Select the thread you are interested in then click on 'Stack' This will reveal the list of loaded DLLs and the method called
You should get something like this:
Note that the above would work if PE can resolve symbols. This page provides an example on how to enable symbol resolution in Process Explorer : http://windowsexplored.com/2012/01/31/resolve-symbols-in-process-explorer-monitor-without-installing-the-debugging-tools/
1.A simple approach will be to add into Main() function
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
and the handler will be something like
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
string errorMessage = e.ExceptionObject.ToString();
Logger.Error(e.ExceptionObject.ToString());
Current.Shutdown(1);
}
2.you can use ProcDump with the flag "-e" to catch unhandled exceptions.
for example myApp.exe:
Procdump -ma -e -w myApp.exe C:\temp\fe.dmp
and then you will need to load some stuff for winDB
1. load the dump file into WinDBG
2. .loadby sos clr in winDBG
3. !printexception
0:005> !printexception
Exception object: 0000000002becc68
Exception type: System.NullReferenceException
Message: Object reference not set to an instance of an object.
InnerException: <none>
StackTrace (generated):
SP IP Function
000000001B94F190 000007FF7E551B74 myApp!myApp.MainForm+...
000000001B94F220 000007F8010FFD85 mscorlib_ni!System.Threading...
000000001B94F380 000007F8010FFAE9 mscorlib_ni!System.Threading...
000000001B94F3B0 000007F8010AC31F mscorlib_ni!System.Threading...
000000001B94F400 000007F8010AC92A mscorlib_ni!System.Threading... ...
you might need SOSEX extension as well
Related
I have quite an unusual problem where if there is a missing DLL on the client machine, the application will freeze and display the standard "The application is not responding". However, as I know what the issue is, I'd like to find a way to catch this exception (Missing DLL) and display the message in a dialog displaying meaningful information to help identify which DLL is missing. This will allow the application to have a more graceful death.
Upon debugging on the client machine, I receive the error:
A first chance exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll
Additional information: Could not load file or assembly 'Some.DLL' or one of its dependencies. The system cannot find the file specified.
In release however, the application crashes and is not responding.
Looking at the documentation for this error, a XamlParseException usually occurs inside the InitializeComponent(); method:
For pages of an application, when the XamlParseException is thrown, it is usually in the context of the InitializeComponent call made by your page class, which is the entry point for the WPF application model's usage of the WPF XAML parser at the per-page level. Therefore another possible handling strategy is to place try/catch blocks in InitializeComponent. However, this technique does not integrate well with templates, visual design surfaces and other generated sources that hook up InitializeComponent.
So, I can do something like this:
public MyView()
{
try
{
InitializeComponent();
}
catch (XamlParseException ex)
{
//Do something useful with the error.
}
}
This is certainly possible, however it would require using this code in practically all controls, which is obviously ridiculous. Not to mention that it doesn't really solve the issue of a missing DLL.
So, my questions are:
Is it possible to trap a missing DLL and display a message containing the name of said DLL?
Is there a more elegant way of catching a XamlParseException?
Thanks.
Yes, it is certainly possible.
To do this, you will need to override what happens when the application first starts up.
Open your Application.xaml.vb, and add the following code:
protected override void OnStartup(StartupEventArgs e)
{
// add an event handler for the UnhandledException event
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(HandleException);
// start up the application
base.OnStartup(e);
}
// what to do when the exception is thrown
void HandleException(object sender, UnhandledExceptionEventArgs e)
{
// do something with the exception
MessageBox.Show(e.ExceptionObject.ToString());
}
The output from the e.ExceptionObject.ToString() contains the problem. In the case you describe, there will probably be nested exceptions, the inner one stating : System.IO.FileNotFoundException: Could not load file or assembly '{missing DLL name here}' or one of its dependencies. The system cannot find the file specified. at {Project}.{where the error was thrown}
I have a main application (in C#), which parses an image database, and then pipes those images into a C++ DLL to have them analysed. Now for some reason every 200 images or so, it throws an error. It doesn't always throw the error at the same image, but just at a random image (sometimes an image passes though the analysis, the other time it throws an error).
Can I somehow make my DLL throw an exception to the C# GUI with information on where in the C++ code the error originates from? The code itself should run fine, and I cannot find where the error is coming from, so I need some help from the DLL to identify at least where it happens.
Any help would be appreciated, I found nothing on that so far.
Just use the debugger to diagnose this. Enable the unmanaged debugger with Project + Properties, Debug tab, tick the "Enable unmanaged code debugging" option.
"it throws an error" is too vague to give specific advice. But you'll want to check the Thrown checkbox in the Debug + Exceptions dialog. Tick "C++ exceptions" and/or "Win32 exception", depending on the type of exception that's being thrown. If you don't know then tick all of them.
If you are not able to get the error when debugging it, in your C++ dll write to output the function that you are in.
For instance, if you have func1, func2, func3 in the dll then write out their names every time you enter and exit each function. When you run the program you will be able to narrow it to the function that is causing the exception, then you can add similar outputs after each line in the function to find the code that is throwing the exception.
I need to write a static List to a text file when a DLL is unloaded. I've tried doing this on AppDomain.CurrentDomain.DomainUnload but it crashes with the error "DefaultDataCollection failed: 0x8007001f".
What is the best way to do this?
Thanks,
Joe
0x8007001f
That's a WIN32 error (the 7 in the middle is FACILITY_WIN32): ERROR_GEN_FAILURE:
A device attached to the system is not functioning.
So you need to look at the exception type and stack trace to get more details of what is failing.
AppDomain.CurrentDomain.DomainUnload
but remember the documentation has the caveat:
This event is never raised in the default application domain.
I have a C# application (project A) that requires X.dll. I have added the project that produces X.dll to A as a reference in visual studio. I have also added the release build of X.dll to a resource file in A as a binary. I have told project A not to copy X.dll to the output directory.
Now I want A.exe to load, say "hey I can't find this file", then look in the resource file and use Assembly.Load(byte[]) get X.dll back. I have the code that re-magicifies the DLL back, however this code never get called.
Currently I have a bone simple project, just trying to get it to work. It compile OK. When I run it, I get a FileNotFoundException on X.dll.
I have:
[STAThread]
static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
But the breakpoint in *CurrentDomain_AssemblyResolve* never gets hit. I get a FileNotFoundException immediately. Surely there is something I a missing?
This question seems to be very similar to what you are trying to achieve, and it worked for the asker.
Merge .dll into C# Assembly?
Are you doing something differently? Specifically, if you're targetting an older version of the .NET Framework, maybe that's a hint for understanding why your application is behaving differently.
Another direction, use a tool such as Fusion Log Viewer to analyze what was going on when you tried to load the assembly. This may give some more hints. If you manage to get log information, posting it in the question may help someone figure it out.
EDIT: Another explanation, following your comment.
Well, now I think I know what the problem is.
In your Main method, you are refering to the type in the other dll. But you are doing it in static code, i.e. you use the type explicitly in the code (as opposed to loading it dynamically by its name).
Why is this a problem? The CLR tries to load your assembly in order to JIT Main itself.
Your FileNotFoundException was thrown while Main was being compiled. Main didn't even start running, and therefore your event handler wasn't registered.
A simple way to check if I'm right is to change the code to something like this:
static public void Main(string[] args)
{
AppDomain.CurrentDomain.AssemblyResolve += MyEventHandler;
MyMain();
}
// The CLR will actually try to load your assembly before even starting the execution
// of this method. It needs the assembly in order to JIT the method because it has to
// know the Thing type.
static public void MyMain()
{
using(var thing = new Thing())
{
// ...
}
}
The important difference is that Main has no dependency on another assembly, so there will be no problem to JIT and run it.
By the time MyMain is being JIT'ed, your event handler is already in place so you can manually load the assembly.
By the way, to avoid another possible similar pitfall, make sure that the class in which Main is defined doesn't have any field with a type from the other assembly, because in this case also, the CLR will try loading the assembly before Main starts, in order to compile it.
I am using this - otherwise excellent - vb tab control in one of my c# apps. When the app using it is installed on another machine, Windows tells the user in its usual friendly and descriptive manner that "The application encountered a problem and needs to close". I guess the control has some hidden vb-related dependency, but what can that be?
Any ideas guys?
Since the tab control appears to be managed code as well, your 'crash' is most likely an unhandled .NET exception.
Looking at the error details (by expanding the error dialog using the button provided for that purpose...) should give you the exception message, which should give you an idea of what's going on. If it's a missing dependency DLL, the name should be included in the message.
To get the full exception, including the stack trace, one of the following should work:
Least effort: in the first line of your own managed code, add an unhandled exception handler which shows the full exception in a message box or logs it to a file prior to rethrowing it
Medium effort: attach a debugger to the process on the client machine. If it's on your local network, setting up remote debugging should be trivial, and should also allow you to debug exceptions that occur prior to your first line of code executing (which may very well be the case if the error is binding-related...)
Most effort: obtain the crash dump file from the client machine, and look at the managed exception using Windbg and the SOS debugging extensions. Getting productive with the tools involved will take some time, but on the plus side will teach you valuable debug ninja skills that will allow you to tackle pretty much any 'mysterious crash'...
BTW, all standard 'VB dependencies' are part of the default .NET Framework install, so that's not your problem -- only the exact exception (and possibly stack trace) will tell you what's going on.
Click the 'What data does this error report contain?' button and there will be more descriptive info. (i.e. type of the thrown exception, module etc.).
For additional info see Dr. Watson vs. CLR.
Is the dll containing the control distributed with your app? Perhaps you have a dependancy in the GAC thay you are missing?