Tuesday, March 20, 2018

VisualTreeChanged Error when Debugging VSIX

I just had an odd thing happen. I tried to debug a VSIX project in VS 2015. When I ran it, I got an error that said:

Message: An unhandled exception of type 'System.InvalidOperationException' occurred in PresentationCore.dll
Additional information: The visual tree has been changed during a 'VisualTreeChanged' event.

At first, I thought it might be related to the issue VS 2017 caused with VSIX projects. But this was a different error. After Googling, I discovered here that you could fix it by disabling Enable UI Debugging Tools for XAML.

Tools --> Options --> Debugging --> General --> Uncheck Enable UI Debugging Tools for XAML.

Monday, January 1, 2018

VSIX Winforms Toolpane

The other day I wanted to create a Visual Studio Toolpane window and I wanted to create it using Winforms (by default, the toolpanes use WPF).

After much research, I got it to work. These are the steps I followed:

I've tested these steps with Visual Studio 2015 & Visual Studio 2017.

  1. Create a new Extensibility project
    1. In Visual Studio, from the File menu, select New --> Project.
    2. In the New Project dialog, one the left, under Visual C#, select Extensibility.
    3. On the right, select VSIX Project.
    4. Give the project a name. In this example, I'm calling it MySampleVSIXProject
  2. Add a Visual Studio Package
    1. Right-click the project in Solution Explorer and select Add --> New Item
    2. In the Add New Item dialog, on the left, expand Extensibility and select VSPackage.
    3. On the right, select Custom Tool Window.
    4. Give the tool window a name. In this example, I'm calling it MySampleToolWindow.cs
  3. Add a Winforms User Control
    1. Right-click the project in Solution Explorer and select Add --> New Item
    2. In the Add New Item dialog, on the left, select Windows Forms
    3. On the right select User Control
    4. Give the User Control a name. In this example, I'm calling it MySampleUserControl.cs
    5. Drag a label to the control so we can see something when we run it. Change the Text property. In this example, I changed it to "I'm a Winforms Control".
  4. Substitute our Winform Control for the WPF Control
    1. Open the MySampleToolWindow.cs file. It should look something like this (I've removed the comments for simplicity):
    2. 
        public class MySampleToolWindow : ToolWindowPane
        {
         public MySampleToolWindow() : base(null)
         {
          this.Caption = "MySampleToolWindow";
          this.Content = new MySampleToolWindowControl();
         }
        }
      
       
    3. Add a field to the MySampleToolWindow class. Make it of type MySampleUserControl and name it control.
    4. Then comment out the line that says "this.Content = new MySampleToolWindowControl();"
    5. Under the commented out line, add a line to create an instance of our control.
    6.   public class MySampleToolWindow : ToolWindowPane
        {
         public MySampleUserControl control; 
         public MySampleToolWindow() : base(null)
              {
                  this.Caption = "MySampleToolWindow";
                  //this.Content = new MySampleToolWindowControl();
                  this.control = new MySampleUserControl();
              } 
        }
       
    7. Add a using System.Windows.Forms; statement at the top of the code.
    8. Next, add this code to the class:
    9.         public override IWin32Window Window
              {
                  get
                  {
                      return (IWin32Window)control;
                  }
              }
       
      It should now look like this:
          public class MySampleToolWindow : ToolWindowPane
          {
              public MySampleUserControl control; 
              public MySampleToolWindow() : base(null)
              {
                  this.Caption = "MySampleToolWindow";
                  //this.Content = new MySampleToolWindowControl();
                  this.control = new MySampleUserControl();
              }
      
              public override IWin32Window Window
              {
                  get
                  {
                      return (IWin32Window)control;
                  }
              }
          }
       

Now we can run the project. In the experimental version of Visual Studio that opens, from the View menu, under Other Windows, you should see our window ("MySampleToolWindow".) Click it to open our window. It opens in a window by itself.

That's great. But what if we want it to open already docked to the Solution Explorer panel?

That's easy. We just have to add some attributes. Open the MySampleToolWindowPackage.cs. On the MySampleToolWindowPackage class, find the ProvideToolWindow attribute. It should look like this:

[ProvideToolWindow(typeof(MySampleToolWindow))]
 

We'll add these Style and Windows attributes to it:

[ProvideToolWindow(typeof(MySampleToolWindow),  
    Style = Microsoft.VisualStudio.Shell.VsDockStyle.Tabbed,  
    Window = "3ae79031-e1bc-11d0-8f78-00a0c9110057"))]
 
According to this MSDN page:
"The first named parameter is Style and its value is Tabbed, which means that the window will be a tab in an existing window. The docking position is specified by the Window parameter, in this case, the GUID of the Solution Explorer."

Now if we run it, it will show up next to the Solution Explorer:

At this point, you can optionally delete the MySampleToolWindowControl.xaml file. This is the WPF control that we're not using.

Thursday, December 28, 2017

Visual Studio 2015 VSIX Project Stopped Working

Yesterday I opened up a VSIX project to add a new feature. This is a Visual Studio 2015 project that I hadn't worked on in a few months. It worked fine a few months ago, but now, all of the sudden, it wouldn't build. What's going on?

The error message I was getting stated:

"Cannot find wrapper assembly for type library "EnvDTE100". Verify that (1) the COM component is registered correctly and (2) your target platform is the same as the bitness of the COM component."

After Googling, I found from this site that if you install Visual Studio 2017 on your machine, it will affect your references to the EnvDTE assemblies. I had recently installed VS 2017. Thankfully, the site also contained the solution:

"In old VSIX projects: Remove old COM references to EnvDTE, EnvDTE80, EnvDTE90 and EnvDTE100. Add new references using Assemblies | Extensions tab and select EnvDTE, EnvDTE80, EnvDTE90, EnvDTE100. The project should build now."

I updated my references and everything started working again.

Tuesday, May 9, 2017

Deleting Files in Visual Studio/TFS Taking a Long Time

I needed to delete some files from source control and noticed that it was taking Visual Studio/TFS about 30 seconds to delete a file (move it to the delete pending list). Since I needed to delete a lot of files, you can imagine how annoying this was. So, I fired up good old Process Monitor and started watching devenv.exe. Then I went into Source Control explorer and deleted a file. Suddenly Process Monitor was full of folder accesses. Dozens of folders were being scanned. After some research, it turned out that when I deleted a file for some reason Visual Studio was looking through all the folders in the same workspace as the file.

So, I created a new workspace and put my project and only that project in the workspace. Now when I try to delete a file it happens very quickly.
Lesson learned.

Thursday, August 11, 2016

More Quotes I Like

Here's some more quotes I've run across that I like: 


"The faster a program converts a task from not-finished to finished, the happier the user will be." -- unknown

"The only value that your software ever has or ever will have is the degree to which it increases the happiness of its users." -- unknown


"You don't want to not have problems. You want to have better problems." -- John Sonmez

Monday, May 2, 2016

Creating a new SSMS Ecosystem Project Plugin

I recently wanted to create an SSMS plugin so I was happy to run across Red Gate’s SSMS ecosystem project. It comes with the C# code for a sample plugin, which is nice. But I couldn’t find any documentation on how to setup a new plugin from strach. It wasn’t hard to figure out though.

One Time Setup

The first thing you need to do is to install the Red Gate SSMS Ecosystem Framework. This only has to be done once – it doesn’t have to be repeated for every plugin you write.

Each Time Setup

Here are the steps to follow in Visual Studio for every plugin you create:

1) Create a new Class Library

2) Search Nuget for “Redgate SSMS” and install the RedGate.SIPFrameworkShared package.

3) Rename Class1 to something more fitting.

4) At the top of your code add “using RedGate.SIPSharedFramework”.

5) Create a registry entry for your plugin. The location will depend on whether you’re running a 32-bit or 64-bit version of Windows.

32-bit: HKLM\SOFTWARE\Red Gate\SIPFramework\Plugins

64-bit: HKLM\SOFTWARE\Wow6432Node\Red Gate\SIPFramework\Plugins

At this location create a new String Value. Name it the name of your plugin. Then make the value the path to your project’s dll.

6) Modify your class to inherit from ISsmsAddin4

7) Implement the members of this interface. 

    
    public class MyPlugin : ISsmsAddin4
    {
        public string Version { get { return "1.0.0.0"; } }
        public string Description { get { return "Your add-in's description"; } }
        public string Name { get { return "Your add-in's name"; } }
        public string Author { get { return "Plugin Author"; } }
        public string Url { get { return @"https://example.com"; } }

        public void OnShutdown()
        {
            // Your code here
        }

        public void OnLoad(ISsmsExtendedFunctionalityProvider provider)
        {
            // Your code here
        }

        public void OnNodeChanged(ObjectExplorerNodeDescriptorBase node)
        {
            // Your code here 
        }
    }

 

8) Using the code Red Gate’s sample add-in as your guide, you can now begin to create your plugin.

See the Red Gate website for more information on debugging your plugin.

Friday, March 25, 2016

“Semicolon Mode”

I think I coined a new term this week.

Several C-like languages (C#, Javascript, Objective-C, etc.) end statements with a semicolon. Other languages (Visual Basic, Python, etc.) don’t.

I had been writing some C# for a while and switched over to work on a Visual Basic project. I found myself putting semicolons at the end of the VB lines and said to myself: “Hey, I’m still in ‘Semicolon Mode’”. Smile