navigation
 Tuesday, July 24, 2007

While having some fun with the Visual Studio SDK I ran across a great example of a Navigation window by Gaston Milano.  It's a great sample to start with if you would like to dive into Visual Studio Package development.  One item of note that I found while using the navigation window on a very large project is that Visual Studio 2005 kept crashing everytime the window would be brought up.  I noticed that before VS crashed it had a difficult time drawing things. I immediately thought of a GDI leak.  I opened up Task Manager and checked the GDI objects and sure enough every time I openned the window the GDI object count would skyrocket upwards, never to return to a sane GDI count again.  VS crashed after reaching a count of about 10,000 GDI objects and I don't blame it for doing that either :) 

The offending routine, the getter for the HierarchyItem::Icon property in HierarchyItem.cs, calls a method NativeMethods.ImageList_GetIcon() which merely vectors off into the win32 version of ImageList_GetIcon().  Looking at the MSDN documentation for this routine you'll notice that the remarks at the end state

"It is the responsibility of the calling application to destroy the icon returned from this function using the DestroyIcon function"

Looking at the code you'll notice that DestroyIcon is never called on the temporary HICON returned from this call so every time this routine is called I noted 2 HICONs being leaked.  And on my large project, this really started adding up.

The fix?

Change the following code in HierarchyItem.cs:

      int handleIcon = NativeMethods.ImageList_GetIcon((int)imageList, (int)index, hbmMask);
      try {
          this.icon = (Icon)Icon.FromHandle((IntPtr)handleIcon).Clone();
      }
      catch (ArgumentException) {
      }
To:
int handleIcon = NativeMethods.ImageList_GetIcon((int)imageList, (int)index, hbmMask);
try {
     this.icon = (Icon)Icon.FromHandle((IntPtr)handleIcon).Clone();
     NativeMethods.DestroyIcon(handleIcon); // <== added to destroy the temp HICON
    } catch (ArgumentException) {
    }

And add a reference to DestroyIcon in the NativeMethods class like so:

        [DllImport("USER32")]
        public static extern int DestroyIcon(int HICON);
Hope that helps any of you running into similar problems.
posted on July 24, 2007  #    by Adam Markowitz  Comments [0]
 Thursday, July 12, 2007

While working with Visual Studio and wishing that feature X existed, I decided to delve into the Visual Studio Extensibility layer and see what it can do.  There are 3 main ways to extend the VSIDE which are Macros, Plugins, and Packages so I opted to play with managed packages (I like C# and wanted full integration into the IDE).

After downloading the Visual Studio 2005 SDK and completing development of my package I needed to deploy it.  I ran into a number of issues deploying my package, mostly related to issues with the Package Load Key.  Following are the steps that I came up with for deploying a package.

  1. Create a new VSIP membership account if you do not already have one (go to the VSIP affiliate site to sign up if you are not a member yet)
  2. Login using your passport account at the vsip members
  3. Once logged in, you must Create a new product
    1. Click on the Products link
    2. Click on the Create New Product link and fill out the information for your package
  4. After your product is created, click on the View/Request PLK link
  5. Fill in the information as it appears in your VSPackage and click the Request PLK button
  6. Microsoft will review your product and notify you that the PLK has been approved or denied
  7. If the PLK has been approved, log back into your VSIP member account, click on Products and then View/Request PLK
  8. Add a new numbered resource to your package with the PLK as its value
  9. Modify the ProvideLoadKey attribute in your package source to reference the resource number for your PLK

Microsoft requires that each deployed Package be given a key generated by and registered with Microsoft.  The generated key is called a Visual Studio Package Load Key, or PLK and must be requested from your VSIP, or Visual Studio Industry Partner, account (Note that if you are not a VSIP member you must sign up).  The PLK is a digest based on information specific to the Package that you have created (Package GUID, Package Name, Product Name, Company Name) allowing for a higher probability of unique values between packages.  The PLK also allows Microsoft to keep track of all released 3rd-party packages via their signature.  Be aware that PLKs are finicky so you must be sure to use the EXACT same information for both the Package and what was used to generated a PLK.

    Here are some useful links I came across regarding PLKs when I was getting my package ready for deployment:
    posted on July 12, 2007  #    by Adam Markowitz  Comments [0]