Get your Visual Studio toolbox in fit


So, it has been a while since I joined the club of those who faced the intimidating

Loading toolbox content from package Microsoft.VisualStudio.IDE.Toolbox.ControlInstaller.ToolboxInstallerPackage
‘{2C98B35-07DA-45F1-96A3-BE55D91C8D7A}’

problem, every time I opened a new instance of Visual Studio and used the XAML designer.

After some search, I found a decent solution. Mind you, do not follow the first workaround described on Microsoft Connect because you will just reset the Toolbox and later the problem will reappear. The solution that worked for me is a combination of two resources I found. The first one, describes the problem. Essentially,  the Toolbox has some invalid entries that cause the delays and there is a specific procedure to find out which these entries are: You have to launch VS by the command line using the parameter /log and then parse the log file to find the time consuming entries. Each of these entries has a GUID that corresponds to registry keys, as well as a description. Judging by the description, you can delete these registry keys and/or reinstall missing components. When you have finish with this, you can force the Toolbox to be regenerated by following the instructions here: http://michaelcrump.net/fixing-a-broken-toolbox-in-visual-studio-2010-sp1

Now, as I said, an important part of all the above is to parse the log and find the time consuming entries. This is not a very easy task, as the XML formatted log file has multiple “entry” elements like this:

<entry>
<record>61</record>
<time>2012/03/19 11:12:50.224</time>
<type>Information</type>
<source>VisualStudio</source>
<description>End package load [Visual Studio Source Control Integration Package]</description>
<guid>{53544C4D-E3F8-4AA0-8195-8A8D16019423}</guid>
</entry>

What you have to do, is to compare the value of <time> element to the value of <time> element of the next <entry> element. I had 1298 entries so searching by scrolling was out of the question, since we can use LINQ to do it for us:

First, I declared a class to represent each <entry>

Class Entry     
    Public Property Record() As Integer
    Public Property Time() As DateTime
    Public Property Source() As String
    Public Property Description() As String
    Public Property Duration() As TimeSpan
End Class
class Entry     
{         
    public int Record { get; set; }
    public DateTime Time { get; set; }
    public string Source { get; set; }
    public string Description { get; set; }
    public TimeSpan Duration { get; set; }
}

Then, I parsed the log file using the following code:

        Dim logFile = "log file path + name here"
        Dim doc = XDocument.Load(logFile)

        Dim entries = doc...<entry>.Select(Function(e) New Entry() With {
                                                        .Record = e.Element("record").Value,
                                                        .Time = CDate(e.Element("time").Value),
                                                        .Source = e.Element("source"),
                                                        .Description = e.Element("description")})

        entries = entries.Zip(entries.Skip(1), Function(e1, e2)
                                                   e1.Duration = e2.Time - e1.Time
                                                   Return e1
                                               End Function).
                          OrderByDescending(Function(e) e.Duration).
                          Take(20)

C# guys might as well use this code:

            var logFile = @"log file path + name here";
            var doc = XDocument.Load(logFile);

            var entries = doc.Descendants("entry").Select(e =>
                new Entry()
                {
                    Record = (int)e.Element("record"),
                    Time = (DateTime)e.Element("time"),
                    Source = e.Element("source").Value,
                    Description = e.Element("description").Value
                });
            entries = entries.Zip(entries.Skip(1), (e1, e2) =>
                {
                    e1.Duration = e2.Time - e1.Time;
                    return e1;
                }).OrderByDescending(e => e.Duration).Take(20);

Now, you can display the entries in question. Alternatively, you can filter the entries collection for descriptions that contain the text “failed”. These entries might or might not have long duration but are useless never the less and represent packages that does not exist for various reasons such as an incomplete uninstall. That was exactly my case, as I had previously uninstalled the Oracle Developer Tools. Obviously (and not surprisingly) Oracle did sloppy job with the uninstaller.

Advertisements

LINQPad: Παίζω και μαθαίνω


Το LINQPad είναι ένα database query tool που όμως αντί να χρησιμοποιεί SQL, χρησιμοποιεί LINQ! Μπορεί κανείς να γράψει SQL statements, C# expressions ή statements και VB expressions ή statements, να εκτελέσει τον κώδικα και κατόπιν να δει τα αποτελέσματα ή το αντίστοιχο lambda expression ή το SQL statement. Αυτό το χαρακτηριστικό, όπως επίσης ότι έρχεται μαζί με 200 παραδείγματα, το καθιστά ένα πολύ δυνατό εργαλείο για εκμάθηση. Επιπρόσθετα η υποστήριξη VB και C# σύνταξης προσφέρεται για να ελέγξει κανείς τις περιπτώσεις όπου ένα query δεν μεταφέρεται πλήρως ανάμεσα στις δύο γλώσσες (ναι, υπάρχουν τέτοιες περιπτώσεις, περισσότερα σε προσεχές post). Μπορείτε να το βρείτε στο http://www.linqpad.net/


Γκαρσόν! Ένα καλοψημένο entity παρακαλώ!


Στο Visual Basic Team Blog έχει ξεκινήσει μια νέα σειρά από posts με τίτλο "LINQ Cookbook". Αποτελούνται από "recipes", η κάθε μία εκ τω οποίων δείχνει το τι μπορεί να κάνει κανείς με το LINQ. Μέχρι στιγμής έχουμε φτάσει στην 5η συνταγή και μάλιστα οι συγγραφείς είναι ανοιχτοί για παραγγελίες.

Enjoy!