Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to get more information on an exception

I created a solution in visual studio 2008 on windows 7, 64 bit.

It works.

When I move it onto another machine, also win 7, 64 bit, it crashed with almost no information.

The original issue was this:

call was rejected by callee

I then implemented this solution:

how to properly GetTypeFromProgID for visual studio 2008

However, now my issue is that when I run the executable on a different machine, the program is crashing immediately with the following information:

Description:
  Stopped working

Problem signature:
  Problem Event Name:   APPCRASH
  Application Name: EmailSalesVolumeSolution.exe
  Application Version:  1.0.0.0
  Application Timestamp:    508064dd
  Fault Module Name:    KERNELBASE.dll
  Fault Module Version: 6.1.7601.17932
  Fault Module Timestamp:   503285c2
  Exception Code:   e0434f4d
  Exception Offset: 000000000000caed
  OS Version:   6.1.7601.2.1.0.256.48
  Locale ID:    1033

Read our privacy statement online:
  http://go.microsoft.com/fwlink/?linkid=104288&clcid=0x0409

If the online privacy statement is not available, please read our privacy statement offline:
  C:\Windows\system32\en-US\erofflps.txt

I wrapped the code in a try/catch, and still did not get a proper error message:

static void Main()
{
    try
    {
        EnvDTE80.DTE2 dte;
        object obj = null;
        System.Type t = null;

        // Get the ProgID for DTE 8.0.
        t = System.Type.GetTypeFromProgID("VisualStudio.DTE.9.0",
          true);
        // Create a new instance of the IDE.
        obj = System.Activator.CreateInstance(t, true);
        // Cast the instance to DTE2 and assign to variable dte.
        dte = (EnvDTE80.DTE2)obj;

        // Register the IOleMessageFilter to handle any threading
        // errors.
        MessageFilter.Register();
        // Display the Visual Studio IDE.
        dte.MainWindow.Activate();


        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Application.Run(new Form1());

        // For example, get a reference to the solution2 object
        // and do what you like with it.

        // All done, so shut down the IDE...
        dte.Quit();
        // and turn off the IOleMessageFilter.
        MessageFilter.Revoke();

    }
    catch (Exception e)
    {
        MessageBox.Show(e.ToString());
    }
}

How can I identify where exactly the exception occurred and WHAT IS the exception?

I do have some unmanaged code:

using System;
using System.Collections.Generic;
using System.Text;
using EnvDTE;
using EnvDTE80;
using EnvDTE90;
using System.Runtime.InteropServices;

namespace EmailSalesVolumeSolution
{
    public class MessageFilter : IOleMessageFilter
    {
        //
        // Class containing the IOleMessageFilter
        // thread error-handling functions.

        // Start the filter.
        public static void Register()
        {
            IOleMessageFilter newFilter = new MessageFilter();
            IOleMessageFilter oldFilter = null;
            CoRegisterMessageFilter(newFilter, out oldFilter);
        }

        // Done with the filter, close it.
        public static void Revoke()
        {
            IOleMessageFilter oldFilter = null;
            CoRegisterMessageFilter(null, out oldFilter);
        }

        //
        // IOleMessageFilter functions.
        // Handle incoming thread requests.
        int IOleMessageFilter.HandleInComingCall(int dwCallType,
          System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr
          lpInterfaceInfo)
        {
            //Return the flag SERVERCALL_ISHANDLED.
            return 0;
        }

        // Thread call was rejected, so try again.
        int IOleMessageFilter.RetryRejectedCall(System.IntPtr
          hTaskCallee, int dwTickCount, int dwRejectType)
        {
            if (dwRejectType == 2)
            // flag = SERVERCALL_RETRYLATER.
            {
                // Retry the thread call immediately if return >=0 & 
                // <100.
                return 99;
            }
            // Too busy; cancel call.
            return -1;
        }

        int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee,
          int dwTickCount, int dwPendingType)
        {
            //Return the flag PENDINGMSG_WAITDEFPROCESS.
            return 2;
        }

        // Implement the IOleMessageFilter interface.
        [DllImport("Ole32.dll")]
        private static extern int
          CoRegisterMessageFilter(IOleMessageFilter newFilter, out 
          IOleMessageFilter oldFilter);
    }
    [ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
    InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    interface IOleMessageFilter
    {
        [PreserveSig]
        int HandleInComingCall(
            int dwCallType,
            IntPtr hTaskCaller,
            int dwTickCount,
            IntPtr lpInterfaceInfo);

        [PreserveSig]
        int RetryRejectedCall(
            IntPtr hTaskCallee,
            int dwTickCount,
            int dwRejectType);

        [PreserveSig]
        int MessagePending(
            IntPtr hTaskCallee,
            int dwTickCount,
            int dwPendingType);
    }
}

after installing VS 2008 express on the machine that gave me trouble, i am now getting this:

enter image description here

like image 830
Alex Gordon Avatar asked Oct 18 '12 20:10

Alex Gordon


3 Answers

You can try also to subscribe on AppDomain.CurrentDomain.UnhandledException event:

AppDomain.CurrentDomain.UnhandledException += 
      (sender, e) => MessageBox.Show(e.ExceptionObject.ToString());

Do this at the top of Main method.

like image 107
Sergey Berezovskiy Avatar answered Sep 28 '22 22:09

Sergey Berezovskiy


Try printing more from the Exception:

catch(Exception e)
{
    MessageBox.Show(e.Message + ":\n" + e.StackTrace);
}

You can use this to catch all Inner Excpetions as well:

string except = "Uncaught Exception: ";
while(e != null)
{
    except += e.Message + ";\n";
    e = e.InnerException;
}

If program crashes with no exception then you need to try and attach a Debugger,

You'll need Visual Studio installed on the machine or to be able to use Remote Desktop for remote debugging. How to: Attach to a Running Process

To attach to a running process:

  1. On the Debug menu, select Attach to Process.

  2. In the Attach to Process dialog box, find the program that you want to attach to from the Available Processes list.

    If the program that you want to debug is running on another computer, use the Qualifier list box to select the remote computer. For more information, see How to: Select a Remote Machine.

    If the process is running under a different user account, select the Show processes from all users check box.

    If you are connected through Remote Desktop Connection, select the Show processes in all sessions check box.

  3. In the Attach to box, make sure that the type of code you will debug is listed. The default Automatic setting tries to determine what type of code you want to debug. If the automatic setting is not appropriate:

  4. Click Select.

  5. In the Select Code Type dialog box, click Debug these code types and select the types to debug.

  6. Click OK.

  7. Click Attach.

You MUST compile the executable with DEBUG mode


UPDATE

I see you use Type.GetTypeFromProgID that requires .NET 4.5, Please make sure you have .NET 4.5 installed on the PC that is throwing the error !

It seems that t = System.Type.GetTypeFromProgID("VisualStudio.DTE.9.0", true); is throwing COMException that means that "VisualStudio.DTE.9.0" is not registered in the other PC.

You should add Microsoft Visual Studio 2008 DTE as a dependency for your program.

like image 41
Danpe Avatar answered Sep 28 '22 20:09

Danpe


Your DLL may not be registered on the client machine. Check the DLL that you are calling the COM object for and do a Regsvr32 YouComDllName.dll in a administrative command prompt (right click on the command prompt icon and do Run as Administrator. Depending on if you are using a 32 bit or 64 bit application you may need to either use the copy of Regsvr32 in C:\Windows\System32 or in C:\Windows\SysWOW64 (In a backwards way the 64 bit version is in system32 and the 32 bit version is in SysWOW64)


If just regestering the DLL on your machine does not work run Dependancy Walker on the program on your computer. When you get all of the DLLs that your program touches, check the client computer is not missing any. The DLL you are calling may be there, but a DLL it depends on may not be.

like image 39
Scott Chamberlain Avatar answered Sep 28 '22 20:09

Scott Chamberlain