CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Patrick Smacchia [MVP C#]

September 2007 - Posts

  • Some VisualStudio featurettes that could save me 15mn a day

     

    Here is a list of minor features I would like to have in VisualStudio to make me and my team slightly more productive. It is certainly too late to expect having them implemented in VisualStudio2008 but who knows, it might be still worth mentioning them. Most of them shouldn’t take more than half a day to be implemented.

     

    • When an exception is raised while debugging, I would like a button in the ‘exception was unhandled’ dialog that discard the exception type (i.e in this case I don’t want being advised anymore of any ParseException raised). Even better, I would like to discard this particular throw. The reason is that while debugging, your environment and inputs might create some well-known error conditions that you don't want to be advised again and again. For example when starting NDepend on a disconnected machine, we got an exception because the program cannot check on the web if a new version is available.

     

     

     

    • Alternatively, when you want to discard a custom exception class, the dialog should at least display the list of custom exception classes in your program, or even have some intellisense support. Now, you to have to type or copy/paste the whole exception class name manually, very boring!

     

     

     

    • I want a ‘smart button’ to attach to process. The underlying plumbing should be smart enough to detect which process I recently start from VisualStudio, and it could also learn from the processes I previously attached to from the current opened solution. It could also detects which processes contains an assembly generated by the current configuration of my solution.

     

     

     

    • When starting a compilation, I want to be advised immediately if the assembly file I’m about to override is not currently used by another program to avoid waiting a few seconds for nothing. I would also like to know immediately which process is currently using which assembly I’m about to override (a la ProcessExplorer) and VisualStudio could propose to close them.


    • Since VisualStudio 4.2, I’m forced to edit my numerous conditional symbols with a ridiculous 275px width textBox. Is it that difficult to code a proper conditional symbols editor? It was already the source of a geek joke we had with some colleagues 5 years ago!


     

     

    • I would like that the textBox ‘Start external program’ accepts some paths relative from the currently opened VisualStudio solution because when you work as a team, you have several machines and installation root paths can be different. Also, the textbox could be smart enough to become a combo box that proposes the list of executable assemblies generated by my solution + the ones recently referenced.

     

    • I would like that the textBox ‘Command line arguments’ remember what I typed previously, and propose a list of previous lists of arguments in a combobox for example. I really don’t want to multiply the number of configurations of my solutions just to avoid retyping some convenient ‘Command line arguments’ for smoke testing.

     

     

     

    • Sometime, you accidently trigger the help update and your VisualStudio 2005 used to freeze for minutes! Things got a bit better with VisualStudio2008 beta2 and the minutes were transformed in seconds. It is still way longer than searching on google in a lightweight browser.

     

     

    • I want some facilities to browse the list of code elements (methods/fields) that I’m currently working with. VisualStudio could infer automatically that I’m currently working with a method if I recently modified it or browse for it. You are often editing multiple methods at the same time and it would be awesome to visualize them intuitively to jump from one to another. Obviously, this facility should be cross-files. I found cross-files bookmarks awkward to do this because I don’t want to spend time managing them.

    • And in my dream, I would like that Reflector decompilation facilities be available natively from VisualStudio. I doubt MS will add this feature as long as it doesn't propose a native obfuscator. Believe me or not, but a lot of .NET developers don't even know about Reflector and decompiling facilities from IL, with metadata. Having Reflector decompilation facilities directly available in VS could lead to high pressure on MS. That's my understanding of the situation and I might be wrong. However, the fact is that today, only educated developers have access to the awesome features of Reflector.

     

  • Dissecting a non-deterministic Windows Forms v2 bug

     

    We are glad that we have just released NDepend v2.4 with the thoroughly revamped UI that I talked about a few weeks ago on this blog entry. For those of you that found the NDepend tool for .NET developers too hard to start with, we hope that our work on usability will help.

     

     

    Bug description

     

    As always while doing our final manual tests before releasing, we found a weird bug. We added docking panels a la VisualStudio to the VisualNDepend UI.  After playing around by moving/collapsing/auto hiding all docking panels, the following exception popup suddenly, while hovering with the mouse one of our DataGridView:

     

    ************** Exception Text **************

    System.ObjectDisposedException: Cannot access a disposed object.

    Object name: 'FloatForm'.

       at System.Windows.Forms.Control.CreateHandle()

       at System.Windows.Forms.Form.CreateHandle()

       at System.Windows.Forms.Control.get_Handle()

       at System.Windows.Forms.ToolTip.get_CreateParams()

       at System.Windows.Forms.ToolTip.CreateHandle()

       at System.Windows.Forms.ToolTip.Hide(IWin32Window win)

       at System.Windows.Forms.ToolStrip.UpdateToolTip(ToolStripItem item)

       at System.Windows.Forms.ToolStripItem.OnMouseHover(EventArgs e)

       at System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)

       at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)

       at System.Windows.Forms.MouseHoverTimer.OnTick(Object sender, EventArgs e)

       at System.Windows.Forms.Timer.OnTick(EventArgs e)

       at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)

       at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

     

     

    When you see such a stack panel with none of your method inside, you immediately realize that your evening at work will be longer than expected (and it was the case uh!). We suspected first the framework DXperience from DevExpress on which we rely for docking panels and knock them on their forum. Hopefully, they knew this problem and immediately answered that it is a Windows Forms bug.

     

     

    Reproducing the bug

     

    The DevExpress support kindly provided a small C# project that reproduces the problem (downloadable from here). To reproduce the bug with this project:


    • 1.   Start the application.
    • 2.   Press the "Click" button (do not hover over the toolstripbutton).
    • 3.       Now hover over the toolstripbutton to display the tooltip.
    • 4.       Close the "test form"
    • 5.       Again, hover over the toolstripbutton => ObjectDisposedException

     

    The bug comes from the fact that the docking panel implementation changes the parent window of the underlying ToolTip control assigned to the DataGridView. When hovering the DataGridView after changing its parent window, if the previous parent window object has been disposed, you get the exception.

     

     

    An idea for the fix

     

    Hopefully, I found here a workaround on the ActiproSoftware forum. As DevExpress, ActiproSoftware is a Windows Forms control vendor and, without surprise, they also faced the problem. The idea is to obtain the private underlying tooltip object with reflection, and then call the method RemoveAll() on it when the parent windows is changing. This way you force re-initialization of the link to parent window. The code looks like this:

     

    ToolTip t = (ToolTip)toolStrip1.GetType().GetProperty(
       "ToolTip", BindingFlags.Instance | BindingFlags.NonPublic
    ).GetValue(toolStrip1, null);
     
    t.RemoveAll();
      
        

    A fix not that easy to implement

     

    This code works well when the problem comes from a ToolStrip control, but, of course, it doesn’t work on DataGridView. I wanted to use Reflector to see where was hidden the underlying ToolTip of a DataGridView but unfortunatly I didn't find it. Indeed, the DataGridView is a monster class with more than 10.000 lines of code, 1053 methods, 322 fields and 13 nested classes. I then wrote the following CQL query with NDepend to make sure that the class DataGridView is using directly or indirectly the class ToolTip.

     

    SELECT TYPES WHERE IsUsing "System.Windows.Forms.ToolTip" AND NameIs "DataGridView"

     

    The query told me that DataGridView is using a class that uses ToolTip. To find this intermediate class I used the following CQL query: Which class is directly used by DataGridView and uses directly ToolTip:

     

    SELECT TYPES WHERE
    IsDirectlyUsedBy "System.Windows.Forms.DataGridView" AND
    IsDirectlyUsing "System.Windows.Forms.ToolTip"

     

    The 2 matching classes are the public classes System.Windows.Forms.ContextMenuStrip and the internal nested class System.Windows.Forms.DataGridView+DataGridViewTool. It was then easy to find were the pesky ToolTip object was hidden and we wrote the following code:


    FieldInfo toolTipControlFieldInfo =    

       typeof(DataGridView).GetField(

          "toolTipControl", BindingFlags.Instance | BindingFlags.NonPublic);

     

    FieldInfo toolTipFieldInfo =

       toolTipControlFieldInfo.FieldType.GetField(

          "toolTip", BindingFlags.Instance | BindingFlags.NonPublic);

     

    object toolTipControlInstance =

       toolTipControlFieldInfo.GetValue(m_DataGridViewItems);

     

    ToolTip toolTip =

       toolTipFieldInfo.GetValue(toolTipControlInstance) as ToolTip;

     

    if (toolTip != null) {  //Can be null at init.

       toolTip.RemoveAll();

    }

     

    I know how ugly it is to rely on private implementation but, here we have no choice.

     

     

    Checking that the bug is corrected by .NET3

     

    We found out that the bug was impossible to reproduce on our main development machines because it is in fact corrected with .NET3. I explained in the post .NET 3.5 Core Stuff that, even though Microsoft made the decision to avoid touching the .NET Framework assemblies (such as System.Windows.Forms.dll), they took a chance to correct some bug.

     

    We then used the build comparison feature of NDepend to see if one the method in the buggy stack trace has been modified (interestingly enough, we figured out that 84 methods of System.Windows.Forms.dll were changed, 202 were added and 37 were removed). Here is the CQL query that matches the changed methods in System.Windows.Forms.ToolTip:

     

    SELECT METHODS FROM TYPES "System.Windows.Forms.ToolTip" WHERE CodeWasChanged

     

    The result is the following…

     

    Methods

    NbILInstructions

    SetTool(IWin32Window,String,ToolTip+TipInfo+Type,Point)

    232

    CreateHandle()

    201

    SetToolTipInternal(Control,ToolTip+TipInfo)

    147

    WmPop()

    126

    Hide(IWin32Window)

    88

    SetToolInfo(Control,String)

    59

     

     

    …and indeed the method ToolTip.Hide(), shown in the buggy trace, has been changed (76 to 88 IL instructions). We then used Reflector to see the code change and indeed there is a test…

     

     if (this.GetHandleCreated())

     

    … to check the parent window when hiding the tooltip.

     

     

    Making sure that our users won't be annoyed by the bug

     

    With the hack described, it seemed that everything worked fine. However, I was not confident since the bug is indeterminist and might be still luring around others controls and we then decided to not popup exception whose stack trace contains the string
    "System.Windows.Forms.ToolTip.CreateHandle()".

     

    I know how ugly is this last choice but in the real-world you sometime not have the choice.

  • 2 talks about Code Quality at PrioConference

    My friend Ralf Westphal invited me at the PrioConference to talk about Code Quality. PrioConference will take place 2007 13/14 November in Baden Baden, Germany. Here are the abstracts of my 2 sessions:

     

     

    Dependencies management and Build comparison  (Day 2 / Tracks 2 / 15h - 16h15)

    The motto 'the source code is the design' is getting widely adopted with the success of agile methodologies. However source code bases are still hard to understand. With traditional tools, it is still a burden to answer simple, yet essential, structural questions such as:
    • Who depends on this particular part of the code?
    • Which methods of a component are using which methods of another component?
    • Is there dependency cycles and what should we do to get rid of them?
    • or Which dependencies have been created/changed/removed between these 2 versions?

    In this session, we'll see how to answer this kind of questions by using a new emerging kind of tool for software developers and architects. We'll concretely use the tool NDepend especially adapted for .NET code bases. We'll also present best practices to refactor your code base to ensure sustainable software structure quality in your projects.



     

    CQL vs. FxCop  (Day 1 / Tracks 3 / 17h - 18h15)

    The FxCop tool is a blessing for every .NET developer that cares about quality. The FxCop authors even recently got awarded the Microsoft Engineering Chairman's Award, the highest award for engineering group employees worlwide. FxCop consists of an extensible set of around 200 rules that automatically check, if code correctly uses the .NET framework and abides by some good practices.

    The next step is to allow .NET developers to write their own rules for their own frameworks and applications. Such custom rules might be

    • My UI layer should not directly access my DAL layer,
    • My methods should not be too complex, except the ones automatically generated,
    • My fields' names should abide by these particular regular expressions,
    • Clients of my framework should use my factories to instantiate my classes, or
    • The code of these particular classes is sensible and I want to be advised whenever it is updated.

    In this track, we'll see how to write such custom rules with the FxCop framework. We'll also present some new kind of specific language dedicated to query and constraint code. We'll focus our attention on the Code Query Language (CQL) supported by the tool NDepend. CQL is to code bases what SQL is to relational databases. We'll see how it is especially designed to simplify writing custom rules.

     


     

     

More Posts