Non-Destructive Debugging

Last post 07-21-2008, 10:48 AM by Gary. 14 replies.
Sort Posts: Previous Next
  •  04-14-2008, 1:21 PM 1026

    Non-Destructive Debugging

    Well, if there's one thing I've learned it's that posting my questions here is the magic ingredient to fixing it 5 minutes later.  Here's hopin!

    I have a moderately functional Non-Destructive Debugging processing working.  I can create a new project from a template, hook up the debugging events, type code in the add-in and debug it.  Once the code runs I can hit a button over on my host .exe and see the updated values.  All appears to be well.  The problem is that I'm having really strange behavior when stepping through code in the Add-in, particularly when trying to read values out of HostItem properties.

    For the sake of discussion, let's say I have the following in my Add-In:

    Private Sub DownloadFileDefinition_Startup(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Startup

       Me.Name = "SomeValue"

    End Sub

    I can set a break point on the one line of code and it will stop there.  But, If I hover over the .Name property, or try the Immediate window with "?Me.Name" it will hang up and never return a value.

    However, if I follow these steps exactly, I can read and update the value all I want from the Immediate Window:

    1) Start Debug with a break on [Me.Name = "SomeValue"].

    2) When the break hits, hit F10 to step down to [End Sub].

    3) In the Immediate window type [Me.Name] which returns an expected error since I didn't give it a value.

    4) In the Immediate window type [?Me.Name] and it will show "SomeValue" as expected.

    5) Continue setting and retrieving Me.Name in any way I want.

    6) Hit F5 to exit the method.

    Now for the strange stuff.  If I don't follow these steps exactly, say skip what seems to be an irrelevent step #3, it will hang.  If I jump right to trying to set the value, it will hang.  If I don't F10 past the line of code in the code window, it will hang.

    There seems to be some conversation that needs to go on between the Proxy in Debug Land and the Actual HostItem in the host .exe and if that doesn't happen just so, the IDE gets stuck.  I'm hoping there is some bit of code that I neglected to call before starting the debug, but if that were the case, I'd expect none of it to work.

    Anyone seen this type of madness before?

     

    Thx.

     

     

  •  04-14-2008, 7:51 PM 1027 in reply to 1026

    Re: Non-Destructive Debugging

    Terry,

    This is not a familiar symptom.  We'll take a look.

  •  04-16-2008, 2:35 PM 1032 in reply to 1026

    Re: Non-Destructive Debugging

    Hi Terry!

    I'm trying to reproduce the problem you're seeing and I was wondering how you're supporting Non-destructive Debugging. Do you have the "basic" implementation that starts a new host application or the "advanced" implementation that works with the running host application?

    Thanks!
    Rebecca

  •  04-16-2008, 2:49 PM 1033 in reply to 1032

    Re: Non-Destructive Debugging

    I suppose you'd call it the advanced model.  I have a UI.exe that has no references to VSTA.  It creates an instance of my Host Item Business object (from another project/assembly) which in addition to being the Host Item, also Loads the AddIns into the DebugProcess.  The UI.exe then creates an instance of another Business Object (from a third project/assembly) which contains all the VSTADesignTime code.  In this "Designer" object I have all the code to create the Debug Process and start the debugging.  It then references by path the UI.exe when it registers the debugging stuff with the DTE.  The UI, of course has an instance of the HostObject mentioned above.

    If you need a more clear explaination, let me know.

    Thx.

  •  04-28-2008, 9:49 AM 1064 in reply to 1032

    Re: Non-Destructive Debugging

    I have a relatively simple (if that's possible in this context!) solution that demonstrates the hanging debugger.  How should I get it to you?
  •  04-28-2008, 10:17 AM 1065 in reply to 1064

    Re: Non-Destructive Debugging

    Terry,
    I'm glad you were able to get a repro sample!  Please send it to vstasupport@summsoft.com and we'll take a look.

    Thanks!
    -Melody
  •  04-28-2008, 8:05 PM 1069 in reply to 1065

    Re: Non-Destructive Debugging

    Sent.  Enojoy.
  •  05-03-2008, 6:01 PM 1080 in reply to 1069

    Re: Non-Destructive Debugging

    Now that I have it working, I think your sample is quite cool!

    An aside - I have learned that it is a bad idea to run the VSTA IDE in debug mode when you've kicked off the host application from the debugger. (I seem to vaguely recall this being an issue with VSA, too) From my limited testing, it seems if you DO run the application from the VS debugger, when you are debugging from the VSTA IDE and you try to use the immediate window, any attempt to evaluate a variable results in the IDE hanging. (when you kill the IDE, there is an IPC error)

    Using your sample and following the detailed list of steps in your original post, I can't exactly reproduce the behavior you describe, but I definitely encounter trouble. For example, sometimes the property can be evaluated in the Immediate Window and sometimes the IDE hangs. I have not succeeded in setting the property at all. I don't have an exact handle on it, but it seems that I can evaluate the property once or maybe twice (either with the Immediate Window or by passing the cursor over) and then the debugger seems to get lost. If I put two break points in and try to look at values, I see odd and inconsistent results, too.

    I'm running on Windows XP. What OS are you using?

    The oddest (most disturbing) thing is that the debugger seems to "lose its place" in the source code and the highlighted break points are no longer highlighted even though I haven't stepped past. When in this state, the menu still shows debugging to be active. If I hit Debug/Stop Debugging, it stops and I can sometimes restart debugging - but sometimes the IDE is just hung or the IPC connection is broken.

    I need to write a coherent story about this and send it off to Microsoft for consideration. This kind of behavior can be reproduced with the ShapeAppMacroRecording sample.

  •  05-05-2008, 9:37 AM 1081 in reply to 1080

    Re: Non-Destructive Debugging

    Well, I'm glad you are having trouble too... (I mean that in the best possible way).  I agree that it should be more stabel without running debug against a host that's in debug and clearly that won't be an issue in producdtion.

    I'm also glad you got the sample running as that's the framework for all the work we are doing in our app, and it's sure to come in handy for any future discussions.

    thx.

  •  05-05-2008, 1:12 PM 1082 in reply to 1081

    Re: Non-Destructive Debugging

    Your sample is very nice!

    Say, what OS are you using? I'm using Windows XP.

  •  05-05-2008, 3:11 PM 1083 in reply to 1082

    Re: Non-Destructive Debugging

    XP Pro.

     

  •  06-09-2008, 11:07 AM 1143 in reply to 1083

    Re: Non-Destructive Debugging

    We have some additional information from Microsoft about the threading issues with seamless debugging. As a workaround, Microsoft suggests setting a special registry entry.
     
    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VSTAHost\MY APPLICATION NAME\9.0\AD7Metrics\Engine\{449EC4CC-30D2-4032-9256-EE18EB41B62B}]
    "AllThreadsRunOnFuncEval"=dword:00000001
     
    This will allow you to evaluate variables in the debugger. There remains an issue with evaluating host object properties - to workaround that, the property must be assigned to a local variable and then inspect that variable.
     
    Microsoft promised to provide information about this registry entry - what exactly it does and any potential side effects it may introduce. As soon as that information in available, I'll post that.
     
    So, far, we have no workaround for the seamless debugger running in an MTA instead of an STA, but Microsoft promised to provide additional information on it.
  •  06-23-2008, 11:53 PM 1170 in reply to 1143

    Re: Non-Destructive Debugging

    Here is some information from Microsoft on how to support Winforms or WPF in the seamless debugger:

    It is actually possible for add-in to use WinForm or WPF. For WinForm, you cannot just call form1.Show(), you need to call either ShowDialog or Application.Run to set up the message pump. For WPF, you have to spawn a STA thread to do it.

    For example:

             public void MacroWinForm()

             {

                 bool useNewThread = false;

                 if (useNewThread)

                 {

                     Thread t = new Thread(() =>

                     {

                         Form1 myWinForm = new Form1();

                         System.Windows.Forms.Application.Run(myWinForm);

                     });

                     t.SetApartmentState(ApartmentState.STA);

                     t.Start();

                     t.Join();

                     MessageBox.Show("Winform new thread");

                 }

                 else // works if using ShowDialog, will block if using Show and without using System.Windows.Forms.Application.Run.

                 {

                     Form1 myWinForm = new Form1();

                     myWinForm.ShowDialog(); // Modal

                     //System.Windows.Forms.Application.Run(myWinForm); // Modeless

                     MessageBox.Show("Winform same thread");

                 }            

             }

     

             public void MacroWPF()

             {

                 bool useNewThread = true;

                 if (useNewThread)

                 {

                     Thread t = new Thread(() =>

                     {

                         System.Windows.Window w = new System.Windows.Window();

                         System.Windows.Application app = new System.Windows.Application();

                         app.Run(w);

                     });

                     t.SetApartmentState(ApartmentState.STA);

                     t.Start();

                     t.Join();

                     MessageBox.Show("Winform new thread");

                 }

                 else // Won't work without creating a new thread

                 {

                     System.Windows.Window w = new System.Windows.Window();

                     System.Windows.Application app = new System.Windows.Application();

                     app.Run(w);

                     MessageBox.Show("Winform same thread");

                 }

             }

  •  07-21-2008, 8:45 AM 1207 in reply to 1143

    Re: Non-Destructive Debugging

    FYI... this fix works just fine.  I suppose it would be interesting to know what side-affects it has, but since it's a design-time thing I'm not as concerned so long as it's stable.  Only time will tell that!

    Thx.

  •  07-21-2008, 10:48 AM 1208 in reply to 1207

    Re: Non-Destructive Debugging

    You may prefer to debug in-process, as shown in these 2 changes to ShapeAppMacroRecortdingCSharp.  The only drawback is that the host application is not responsive when debugger is paused during debug steps and breakpoints:

            #region IExternalDebugHost members

     

            /// <summary>

            /// Called before debugging is started. Creates an external process to load the

            /// Macro AddIn in for debugging purposes.

            /// </summary>

            /// <returns>Process ID of the external process created to load Macro AddIn in.</returns>

            int IExternalDebugHost.OnBeforeDebugStarting()

            {

                // Create an External Process

                            //EnsureMacroAddInProcess();

                //return this.macroAddInProcess.ProcessId;

     

    //Use in-process debugging

                int nProcessID = System.Diagnostics.Process.GetCurrentProcess().Id;

                return nProcessID; 

            }

     

            /// <summary>

            /// Called when debugging is started. It first unloads the currently loaded Macro AddIn

            /// and then loads the Macro AddIn in an external process for debugging.

            /// </summary>

            void IExternalDebugHost.OnDebugStarting()

            {

                if (!this.isDebugging)

                {

                    try

                    {

                           this.application.VstaRuntimeIntegration.UnloadCurrentMacroAddin(false);

     

                        // Load Macro AddIn out-of-proc

                        //this.application.VstaRuntimeIntegration.LoadMacrosExProcess(this.macroAddInProcess);

    // Load Macro add-in in-process this.application.VstaRuntimeIntegration.LoadMacrosInProcess();

     

                        this.isDebugging = true;

                    }

                    catch (Exception ex)

                    {

                        this.isDebugging = false;

     

                        // DO NOT RETHROW. Backstop this thread or the application will close.

                        System.Diagnostics.Debug.WriteLine(ex.ToString());

                    }

                }

                else

                {

                    MessageBox.Show("Cannot start multiple debug sessions.", "ShapeAppCSharp", MessageBoxButtons.OK, MessageBoxIcon.Error);

                }

            }

     

View as RSS news feed in XML