none
How to add custom control to Visual Studio 2008 Toolbox? RRS feed

  • Question

  • Hi All,
    I am getting "Package Load Failure" error when I tried *.vsi method. I am looking into Chetan Chudasama's Weblog which explains workaround for Visual Studio 2005 which is not working for Visual Studio 2008.

    I have Visual Studio 2008 Professional Edition which SP 1 installed.

    Thanks in Advance.

    Castle Rider
    The truth is... I am Iron Man!
    Wednesday, October 1, 2008 11:42 AM

Answers


  • Hi Castle Rider,

    Based on my understanding, the ProgID of DTE for Visual Studio 2008 is VisualStudio.DTE.9.0. Thus you need to use VisualStudio.DTE.9.0 instead of VisualStudio.DTE.8.0 when you are working with Visual Studio 2008. I have the following code, and I can add and remove controls from Visual Studio ToolBox.

            static string ctrlPath = @"D:\UCLib.dll";

            void InstallControl()

            {

                // Create an instance of the VS IDE,

                Type type = System.Type.GetTypeFromProgID("VisualStudio.DTE.9.0");

                DTE dte = (DTE)System.Activator.CreateInstance(type, true);

     

                // create a temporary winform project;

                string tmpFile = Path.GetFileNameWithoutExtension(Path.GetTempFileName());

                string tmpDir = string.Format("{0}{1}",Path.GetTempPath(),tmpFile);

                Solution2 solution = dte.Solution as Solution2;

                string templatePath = solution.GetProjectTemplate("WindowsApplication.zip", "CSharp");

                Project proj = solution.AddFromTemplate(templatePath, tmpDir, "dummyproj", false);

                // add the control to the toolbox.

                EnvDTE.Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindToolbox);

                EnvDTE.ToolBox toolbox = (EnvDTE.ToolBox)window.Object;

                EnvDTE.ToolBoxTab myTab = toolbox.ToolBoxTabs.Add("My Tab");

                myTab.Activate();

                myTab.ToolBoxItems.Add("UserControl1", ctrlPath, vsToolBoxItemFormat.vsToolBoxItemFormatDotNETComponent);

                dte.Solution.Close(false);

                Marshal.ReleaseComObject(dte);

                Console.WriteLine("Control Installed!!!");

            }

            void UninstallControl()

            {

                Type type = System.Type.GetTypeFromProgID("VisualStudio.DTE.9.0");

                DTE dte = (DTE)System.Activator.CreateInstance(type, true);

                // create a temporary winform project;

                string tmpFile = Path.GetFileNameWithoutExtension(Path.GetTempFileName());

                string tmpDir = string.Format("{0}{1}", Path.GetTempPath(), tmpFile);

                Solution2 solution = dte.Solution as Solution2;

                string templatePath = solution.GetProjectTemplate("WindowsApplication.zip", "CSharp");

                Project proj = solution.AddFromTemplate(templatePath, tmpDir, "dummyproj", false);

     

                EnvDTE.Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindToolbox);

                EnvDTE.ToolBox toolbox = (EnvDTE.ToolBox)window.Object;

                EnvDTE.ToolBoxTab myTab = toolbox.ToolBoxTabs.Item("My Tab");

                myTab.Activate();

                myTab.Delete();

                Marshal.ReleaseComObject(dte);

                Console.WriteLine("Control Uninstalled!!!");

            }


    Thanks,
    Rong-Chun Zhang


    Please mark the replies as answers if they help and unmark if they don't.
    Thursday, October 2, 2008 7:28 AM

All replies


  • Hi Castle Rider,

    Based on my understanding, the ProgID of DTE for Visual Studio 2008 is VisualStudio.DTE.9.0. Thus you need to use VisualStudio.DTE.9.0 instead of VisualStudio.DTE.8.0 when you are working with Visual Studio 2008. I have the following code, and I can add and remove controls from Visual Studio ToolBox.

            static string ctrlPath = @"D:\UCLib.dll";

            void InstallControl()

            {

                // Create an instance of the VS IDE,

                Type type = System.Type.GetTypeFromProgID("VisualStudio.DTE.9.0");

                DTE dte = (DTE)System.Activator.CreateInstance(type, true);

     

                // create a temporary winform project;

                string tmpFile = Path.GetFileNameWithoutExtension(Path.GetTempFileName());

                string tmpDir = string.Format("{0}{1}",Path.GetTempPath(),tmpFile);

                Solution2 solution = dte.Solution as Solution2;

                string templatePath = solution.GetProjectTemplate("WindowsApplication.zip", "CSharp");

                Project proj = solution.AddFromTemplate(templatePath, tmpDir, "dummyproj", false);

                // add the control to the toolbox.

                EnvDTE.Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindToolbox);

                EnvDTE.ToolBox toolbox = (EnvDTE.ToolBox)window.Object;

                EnvDTE.ToolBoxTab myTab = toolbox.ToolBoxTabs.Add("My Tab");

                myTab.Activate();

                myTab.ToolBoxItems.Add("UserControl1", ctrlPath, vsToolBoxItemFormat.vsToolBoxItemFormatDotNETComponent);

                dte.Solution.Close(false);

                Marshal.ReleaseComObject(dte);

                Console.WriteLine("Control Installed!!!");

            }

            void UninstallControl()

            {

                Type type = System.Type.GetTypeFromProgID("VisualStudio.DTE.9.0");

                DTE dte = (DTE)System.Activator.CreateInstance(type, true);

                // create a temporary winform project;

                string tmpFile = Path.GetFileNameWithoutExtension(Path.GetTempFileName());

                string tmpDir = string.Format("{0}{1}", Path.GetTempPath(), tmpFile);

                Solution2 solution = dte.Solution as Solution2;

                string templatePath = solution.GetProjectTemplate("WindowsApplication.zip", "CSharp");

                Project proj = solution.AddFromTemplate(templatePath, tmpDir, "dummyproj", false);

     

                EnvDTE.Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindToolbox);

                EnvDTE.ToolBox toolbox = (EnvDTE.ToolBox)window.Object;

                EnvDTE.ToolBoxTab myTab = toolbox.ToolBoxTabs.Item("My Tab");

                myTab.Activate();

                myTab.Delete();

                Marshal.ReleaseComObject(dte);

                Console.WriteLine("Control Uninstalled!!!");

            }


    Thanks,
    Rong-Chun Zhang


    Please mark the replies as answers if they help and unmark if they don't.
    Thursday, October 2, 2008 7:28 AM
  • Hi Rong-Chun Zhang,

    I did the mentioned changes. Now the tab item is showing up in the Visual Studio 2008, but the controls are not adding up. FYI, the controls are WPF controls and it is created like Single Assembly multiple controls in it.

    And my sample code to add the controls is,

    using System; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Runtime.InteropServices; 
    using System.IO; 
    using EnvDTE; 
     
    namespace InstallToolboxControls 
        // Definition of the IMessageFilter interface which we need to implement and  
        // register with the CoRegisterMessageFilter API. 
        [ComImport(), Guid("00000016-0000-0000-C000-000000000046"), 
        InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 
        interface IOleMessageFilter // Renamed to avoid confusion w/ System.Windows.Forms.IMessageFilter 
        { 
            [PreserveSig] 
            int HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo); 
            [PreserveSig] 
            int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType); 
            [PreserveSig] 
            int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType); 
        } 
     
        class Program : IOleMessageFilter 
        { 
            [DllImport("ole32.dll")] 
            private static extern int CoRegisterMessageFilter(IOleMessageFilter newFilter, out IOleMessageFilter oldFilter); 
            static string ctrlPath = @"D:\Projects\EAGLE_SUITE_2.0\Framework\Client\Eagle.Windows.Controls\bin\Debug\Eagle.Windows.Controls.dll"
            [STAThread] 
            static void Main(string[] args) 
            { 
                Program program = new Program(); 
                program.Register(); 
     
                if (args.Length > 0) 
                { 
                    if (args[0].Equals("-Install", StringComparison.CurrentCultureIgnoreCase)) 
                        program.InstallControl(); 
                    else if (args[0].Equals("-UnInstall", StringComparison.CurrentCultureIgnoreCase)) 
                        program.UninstallControl(); 
                } 
     
                program.Revoke(); 
     
     
                // to ensure the dte object is actually released, and the devenv.exe process terminates. 
                GC.Collect(); 
                GC.WaitForPendingFinalizers(); 
            } 
            void InstallControl() 
            { 
                // Create an instance of the VS IDE, 
                Type type = System.Type.GetTypeFromProgID("VisualStudio.DTE.9.0"); 
                DTE dte = (DTE)System.Activator.CreateInstance(type, true); 
                 
                // add the control to the toolbox. 
                EnvDTE.Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindToolbox); 
                EnvDTE.ToolBox toolbox = (EnvDTE.ToolBox)window.Object; 
                EnvDTE.ToolBoxTab myTab = toolbox.ToolBoxTabs.Add("Eagle WPF Controls v1.0"); 
                myTab.Activate(); 
                myTab.ToolBoxItems.Add("Eagle.Windows.Controls", ctrlPath, vsToolBoxItemFormat.vsToolBoxItemFormatDotNETComponent); 
                dte.Solution.Close(false); 
                Marshal.ReleaseComObject(dte); 
                Console.WriteLine("Control Installed!!!"); 
            } 
            void UninstallControl() 
            { 
                Type type = System.Type.GetTypeFromProgID("VisualStudio.DTE.9.0"); 
                DTE dte = (DTE)System.Activator.CreateInstance(type, true); 
     
                EnvDTE.Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindToolbox); 
                EnvDTE.ToolBox toolbox = (EnvDTE.ToolBox)window.Object; 
                EnvDTE.ToolBoxTab myTab = toolbox.ToolBoxTabs.Item("Eagle WPF Controls v1.0"); 
                myTab.Activate(); 
                myTab.Delete(); 
                Marshal.ReleaseComObject(dte); 
                Console.WriteLine("Control Uninstalled!!!"); 
            } 
            void Register() 
            { 
                IOleMessageFilter oldFilter; 
                CoRegisterMessageFilter(thisout oldFilter); 
            } 
            void Revoke() 
            { 
                IOleMessageFilter oldFilter; 
                CoRegisterMessageFilter(nullout oldFilter); 
            } 
            #region IOleMessageFilter Members 
            public int HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo) 
            { 
                return 0; //SERVERCALL_ISHANDLED 
            } 
            public int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType) 
            { 
                if (dwRejectType == 2) // SERVERCALL_RETRYLATER 
                    return 200; // wait 2 seconds and try again 
                return -1; // cancel call 
            } 
            public int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType) 
            { 
                return 2; //PENDINGMSG_WAITDEFPROCESS 
            } 
            #endregion 
        } 

    Thanks in Advance

    Castle Rider
    The truth is... I am Iron Man!
    Tuesday, October 7, 2008 2:26 AM

  • Hi Castle Rider,

    If your control is a WPF control, please try to create a temporary WPF project.

    Thanks,
    Rong-Chun Zhang



    Please mark the replies as answers if they help and unmark if they don't.
    Tuesday, October 7, 2008 9:44 AM
  • Rong-Chun Zhang said:


    Hi Castle Rider,

    If your control is a WPF control, please try to create a temporary WPF project.

    Thanks,
    Rong-Chun Zhang



    Please mark the replies as answers if they help and unmark if they don't.


    What does this means?? Temporary WPF Project for what reason? Are you saying that I have to initiate the -install and -uninstall from a WPF application?

    Sorry for late response.



    Castle Rider
    The truth is... I am Iron Man!
    Monday, October 13, 2008 2:46 AM

  • Hi Castle Rider,

    Sorry for that confusion. What I mean is that you need to create a WPF temporary project to install the WPF Control. This is duo to the ToolBox may be different when Visual Studio load different type of project. Thus, Your InstallControl may be something like the following.

            void InstallControl()

            {

                // Create an instance of the VS IDE,

                Type type = System.Type.GetTypeFromProgID("VisualStudio.DTE.9.0");

                DTE dte = (DTE)System.Activator.CreateInstance(type, true);

     

                // create a temporary winform project;

                string tmpFile = Path.GetFileNameWithoutExtension(Path.GetTempFileName());

                string tmpDir = string.Format("{0}{1}",Path.GetTempPath(),tmpFile);

                Solution2 solution = dte.Solution as Solution2;

                string templatePath = solution.GetProjectTemplate("WPFApplication.zip", "CSharp");

                Project proj = solution.AddFromTemplate(templatePath, tmpDir, "dummyproj", false);

                // add the control to the toolbox.

                EnvDTE.Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindToolbox);

                EnvDTE.ToolBox toolbox = (EnvDTE.ToolBox)window.Object;

                EnvDTE.ToolBoxTab myTab = toolbox.ToolBoxTabs.Add("My Tab");

                myTab.Activate();

                myTab.ToolBoxItems.Add("UserCoffntrol1", ctrlPath, vsToolBoxItemFormat.vsToolBoxItemFormatDotNETComponent);

                dte.Solution.Close(false);

                Marshal.ReleaseComObject(dte);

                Console.WriteLine("Control Installed!!!");

            }


    Thanks,
    Rong-Chun Zhang


    Please mark the replies as answers if they help and unmark if they don't.
    Monday, October 13, 2008 3:00 AM
  • Hi Rong-Chun Zhang,

    I have added a Installer Class along with my WPF Class Library and created a Setup project. The Installer class is invoked from the Setup. But still its not showing up. My Installer class looks like,

    namespace Eagle.Windows 
        [RunInstaller(true)] 
        public partial class InstallControls : Installer, IOleMessageFilter 
        { 
            [DllImport("ole32.dll")] 
            private static extern int CoRegisterMessageFilter(IOleMessageFilter newFilter, out IOleMessageFilter oldFilter); 
     
            public InstallControls() 
            { 
                InitializeComponent(); 
                 
                this.AfterInstall += new InstallEventHandler(InstallControls_AfterInstall); 
            }         
     
            private void InstallControls_AfterInstall(object sender, InstallEventArgs e) 
            { 
     
                this.Register(); 
     
                // Create an instance of the VS IDE, 
                Type type = System.Type.GetTypeFromProgID("VisualStudio.DTE.9.0"); 
     
                DTE dte = (DTE)System.Activator.CreateInstance(type, true); 
     
                // add the control to the toolbox. 
     
                EnvDTE.Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindToolbox); 
     
                EnvDTE.ToolBox toolbox = (EnvDTE.ToolBox)window.Object; 
     
                EnvDTE.ToolBoxTab eagleTab = toolbox.ToolBoxTabs.Add("Eagle WPF Controls"); 
     
                eagleTab.Activate(); 
     
                Assembly asm = System.Reflection.Assembly.GetExecutingAssembly(); 
     
                MessageBox.Show(asm.Location); 
     
                foreach (Type modul in asm.GetTypes()) 
                { 
                    // Check for valid controls. 
                    if (modul.IsClass && modul.IsSubclassOf(typeof(Control)) && !modul.IsSubclassOf(typeof(System.Windows.Window))) 
                    { 
                        eagleTab.ToolBoxItems.Add(modul.ToString(), asm.Location, vsToolBoxItemFormat.vsToolBoxItemFormatDotNETComponent); 
                    } 
                }             
     
                dte.Solution.Close(false); 
     
                Marshal.ReleaseComObject(dte); 
     
                this.Revoke(); 
                GC.Collect(); 
                GC.WaitForPendingFinalizers(); 
            } 
     
            private void Register() 
            {  
                IOleMessageFilter oldFilter;  
                CoRegisterMessageFilter(thisout oldFilter);  
            } 
     
            private void Revoke()  
            {  
                IOleMessageFilter oldFilter;  
                CoRegisterMessageFilter(nullout oldFilter);  
            }  
            #region IOleMessageFilter Members  
            public int HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo)  
            {  
                return 0; //SERVERCALL_ISHANDLED  
            }  
            public int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType)  
            {  
                if (dwRejectType == 2) // SERVERCALL_RETRYLATER  
                    return 200; // wait 2 seconds and try again  
                return -1; // cancel call  
            }  
            public int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType)  
            {  
                return 2; //PENDINGMSG_WAITDEFPROCESS  
            }  
            #endregion 
        } 
     
        // register with the CoRegisterMessageFilter API.  
        [ComImport(), Guid("00000016-0000-0000-C000-000000000046"), 
        InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 
        interface IOleMessageFilter // Renamed to avoid confusion w/ System.Windows.Forms.IMessageFilter  
        { 
            [PreserveSig] 
            int HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo); 
            [PreserveSig] 
            int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType); 
            [PreserveSig] 
            int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType); 
        } 

    Correct me if I am wrong in the above code. FYI, the Project is a WPF Class Library. I believe that there won't be any problem with the Visual Studio to identify the correct type.


    Castle Rider
    The truth is... I am Iron Man!
    Friday, October 17, 2008 6:42 AM
  • Hi All,

    I am also using the above code, but a user of mine reported that a dialog is shown with a title of "Security Warning for dummyproj".  How can I prevent this dialog from showing during the installation of our controls into the toolbox of Visual Studio 2008?

    He also gets "An item referring to the file "" was found in the project file "c:\documents and settings\[UserName]\local settings\temp\temp5b6\dummyproj.csproj".  Since this file is located within a system directory, root directory, or network share, it could be harmful to write to this file."  Please note that the [UserName] was put there by me in the above text to keep my user's privacy.

    Any ideas?  All help would be greatly appreciated.  Thank you in advance!

    Craig
    Monday, July 27, 2009 7:04 PM