怎样使控件注册到VS2005 工具箱中

   近来项目做了一些控件,为了让软件开发环境更加统一和方便,制作了控件安装程序,在安装后,控件会自动注册到VS2005的工具箱中,就像DevExpress等控件一样。下面主要来说说怎样让自定义控件自动注册到VS2005工具箱中吧!
     控件自动注册到VS2005工具箱的方法非常简单,尝试中我使用了两种方法,其实核心都只要掌握DTE,EnvDTE80的使用。

    方法一(参考网文):

一、系统环境说明:
   1.系统盘为C盘
   2.VS2005安装目录:C:/Program Files/Microsoft Visual Studio 8

二、操作步骤:
   1.整理要注册到工具箱的控件DLL文件
    首先,在C:/Documents and Settings/[你的用户名]/My Documents/Visual Studio 2005/目录下查找是否有名为[Controls]的文件夹,如果没有则新建此文件夹;然后再在[Controls]文件夹下新建一文件夹,名称自定义(注意,此文件夹的名称就是注册成功后在[工具箱]里的[选项卡]的名称)。这里我把文件夹取名为“MyControls”,之后把要注册到工具箱的控件DLL文件放入“MyControls”文件夹内。
   2.制作注册程序
      (1)新建一个控制台项目;
      (2)添加引用:
      EnvDTE
      文件路径:C:/Program Files/Microsoft Visual Studio 8/Common7/IDE/PublicAssemblies/EnvDTE.dll
      EnvDTE80
      文件路径:C:/Program Files/Microsoft Visual Studio 8/Common7/IDE/PublicAssemblies/EnvDTE80.dll
      Microsoft.VisualBasic
      文件路径:Microsoft.VisualBasic C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Microsoft.VisualBasic.dll
     (3)制作控件的安装程序
EnvDTE80.DTE2 myDTE2  =  (EnvDTE80.DTE2)Microsoft.VisualBasic.Interaction.CreateObject( " VisualStudio.DTE.8.0 " "" );
 try
{
     
if (myDTE2 == null
          {
               MessageBox.Show(
"无法调用DTE!"); 
               return;
          }
      myDTE2.ExecuteCommand(
"Tools.InstallCommunityControls"string.Empty);
      System.Runtime.InteropServices.Marshal.ReleaseComObject(myDTE2);
}

 catch  (Exception ex)
{
      MessageBox.Show(ex.ToString());
}

    (4)编译
   3.运行注册
    关闭VS2005的所有进程,然后运行上一步制作的注册程序。运行完毕后,打开VS2005,我们就可以看到新增加的一个选项卡[MyControls]了,展开此选项卡,就可以看到自己的控件了! ^_^

另外请注意:
    多次运行注册时,如果注册不成功的话,请打开注册表,搜索HKEY_USERS/[名称不同]/Software/Microsoft/VisualStudio/8.0/UserToolBoxControls下是否有你现在要注册的选项卡名,例如:“MyControls”,如果有请先删除,再运行注册程序。

 

很久没有把方法二补上,真的很累,五一就要到了,又没有假,只有在周末稍微有点时间的时候,再加点东西吧。

方法二:

一、创建一个新的控制台程序项目,别忘了添加DTE引用哦,具体就参考方法一。
二、建立控件注册类StandardToolBoxCreator,其中包括一个子类ComponentData,你也可以把独立出来:

         /// <summary>
        
/// 控件数据类
        
/// </summary>

         public   class  ComponentData
        
{
            
public ComponentData(string name, string fullPath)
            
{
                
this._name = name;
                
this._fullPath = fullPath;
            }


            
private string _name;
            
private string _fullPath;

            
/// <summary>
            
/// 控件类型的完全限定名称
            
/// </summary>

            public string Name
            
{
                
get return _name; }
                
set { _name = value; }
            }


            
/// <summary>
            
/// 控件文件的完全路径
            
/// </summary>

            public string FullPath
            
{
                
get return _fullPath; }
                
set { _fullPath = value; }
            }

        }

1.对象初始化的时候读取控件DLL文件列表INI文件ComponentList.ini,每个DLL文件之间用“;”隔开,可以是相对路径也可以是绝对路径,其方法是GetDllFiles();
2.如果有可用的DLL文件则进行注册操作RunCreator(DTE dte)
首先打开一个临时Solution激活DTE,然后获得DTE的工具箱窗体Window中的工具箱ToolBox,再通过工具箱获取选项卡集合,并创建自己的选项卡,最后在自己的选项卡内注册控件。

         #region 变量区

        
static string INIFILE = "ComponentList.ini";
        
static string TABLABLE = "Mr.Cell控件";

        ArrayList DllFileList 
= new ArrayList();
        List
<ComponentData> ComponentDataList = new List<ComponentData>();

        
#endregion


        
#region 构造函数

        
/// <summary>
        
/// 构造函数
        
/// </summary>

        public ToolBoxCreator()
        
{
            GetDllFiles();
        }


        
#endregion


        
#region 获取需要安装的控件Dll文件

        
/// <summary>
        
/// 获取需要安装的控件Dll文件
        
/// <remarks>
        
/// DllFileList 控件Dll文件的绝对路径集合
        
/// </remarks>
        
/// </summary>

        private void GetDllFiles()
        
{
            
try
            
{
                
string text = new StreamReader(INIFILE,Encoding.GetEncoding("GB2312")).ReadLine();
                
if (text == nullreturn;

                ArrayList list 
= new ArrayList();
                list.AddRange(text.Split(
new char[] ';' }));
                Console.WriteLine(
"需要安装的控件文件:/n {0}", text);

                
if (list.Count < 1return;

                
foreach (string  strFile in list)
                
{
                    
string fileFullPath = Path.GetFullPath(strFile);

                    
if (!File.Exists(fileFullPath))
                    
{
                        Console.WriteLine(
"找不到文件:{0}", strFile);
                        
continue;
                    }


                    
this.DllFileList.Add(fileFullPath);
                }

            }

            
catch
            
{
                
throw;
            }

        }


        
#endregion


        
#region 获取所有需要安装的控件数据

        
/// <summary>
        
/// 获取所有需要安装的控件数据
        
/// <remarks>
        
/// <see cref="ComponetData"/>类型的对象集合
        
/// </remarks>
        
/// </summary>

        public List<ComponentData> GetAllComponentsData()
        
{
            List
<ComponentData> list = new List<ComponentData>();

            
for (int i = 0; i < this.DllFileList.Count; i++)
            
{
                
if (this.DllFileList[i].ToString().Trim() == string.Empty)
                    
continue;
                GetAllComponents(
this.DllFileList[i].ToString().Trim(), list);
            }


            
return list;
        }


        
#endregion


        
#region 获取所有需要安装的控件类型

        
/// <summary>
        
/// 获取所有需要安装的控件类型
        
/// </summary>
        
/// <param name="dllFile">Dll文件</param>
        
/// <param name="list"></param>

        private void GetAllComponents(string dllFile, List<ComponentData> list)
        
{
            Assembly assembly;
            
try
            
{
                assembly 
= Assembly.LoadFrom(dllFile);

                
foreach (Type type in assembly.GetTypes())
                
{
                    
try
                    
{
                        
if ((type.IsPublic && !type.IsAbstract) && ((type.IsSubclassOf(typeof(Component)) || typeof(IComponent).IsAssignableFrom(type)) || type.IsSubclassOf(typeof(Control))))
                        
{
                            ToolboxItemAttribute attribute 
= (ToolboxItemAttribute)TypeDescriptor.GetAttributes(type)[typeof(ToolboxItemAttribute)];
                            
if ((attribute != null&& (attribute.ToolboxItemTypeName != ""))
                            
{
                                ToolboxItemFilterAttribute filterAttribute 
= (ToolboxItemFilterAttribute)TypeDescriptor.GetAttributes(type)[typeof(ToolboxItemFilterAttribute)];
                                
if ((((filterAttribute == null|| (filterAttribute.FilterType != ToolboxItemFilterType.Require))) && (type.GetConstructor(new Type[0]) != null))
                                
{
                                    list.Add(
new ComponentData(type.FullName,dllFile));
                                }

                            }

                        }

                    }

                    
catch
                    
{
                        Console.WriteLine(
"类型分析错误!- {0}"new object[] { type.Name });
                        
return;
                    }

                }


            }

            
catch
            
{
                Console.WriteLine(dllFile 
+ "文件错误!");
                
return;
            }

        }


        
#endregion


        
#region 控件注册到工具箱的方法

        
/// <summary>
        
/// 控件注册到工具箱的方法
        
/// </summary>
        
/// <param name="dte"></param>

        public void RunCreator(DTE dte)
        
{
            
if (DllFileList.Count < 1)
            
{
                Console.WriteLine(
"没有任何需要安装的控件文件!");
                
return;
            }


            
string tempProjPath = Path.Combine(Path.GetTempPath(), "tempProj");

            
if (Directory.Exists(tempProjPath))
            
{
                Directory.Delete(tempProjPath, 
true);
            }


            
string fileName = ((Solution2)dte.Solution).GetProjectTemplate("WindowsApplication.zip""CSharp");

            
switch (fileName)
            
{
                
case null:
                
case "":
                    fileName 
= ((Solution2)dte.Solution).GetProjectTemplate("WindowsApplication.zip""VisualBasic");
                    
break;
            }

            
if ((fileName == null|| (fileName == string.Empty))
            
{
                fileName 
= ((Solution2)dte.Solution).GetProjectTemplate("WindowsApplication.zip""csharp");
            }

            dte.Solution.AddFromTemplate(fileName, tempProjPath, 
"temp.cproj"false);
            dte.Solution.Close(
false);
            
//dte.ExecuteCommand("View.PropertiesWindow", "");
            Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindToolbox);
            window.Activate();
            ToolBox box 
= window.Object as ToolBox;
            ToolBoxTabs tabs 
= box.ToolBoxTabs;
            ToolBoxTab tab;

            
try
            
{
                tab 
= FindOrCreateTab(tabs, TABLABLE, false);

                
if (tab != null)
                
{
                    tab.Delete();
                    Console.WriteLine(
"删除工具箱标签[" + TABLABLE + "]");
                }


                tab 
= FindOrCreateTab(tabs, TABLABLE, true);
                dte.ExecuteCommand(
"View.PropertiesWindow""");
                tab.Activate();

                
this.ComponentDataList = this.GetAllComponentsData();

                
if (ComponentDataList.Count < 1return;

                Console.WriteLine(
"开始注册控件");

                
foreach (ComponentData componentData in this.ComponentDataList)
                
{
                    RegComponent(tab, componentData);
                }


                Console.WriteLine(
"添加控件成功!");
            }

            
catch
            
{
                
throw;
            }

        }


        
#endregion


        
#region 注册组件

        
/// <summary>
        
/// 注册组件
        
/// </summary>
        
/// <param name="tab"></param>
        
/// <param name="componentData"></param>

        private void RegComponent(ToolBoxTab tab, ComponentData componentData)
        
{
            
string data = string.Format("{0},{1}", componentData.Name, componentData.FullPath);
            tab.ToolBoxItems.Add(componentData.Name, data, vsToolBoxItemFormat.vsToolBoxItemFormatDotNETComponent);
            Console.WriteLine(componentData.Name);
        }


        
#endregion


        
#region 查找标签或创建标签

        
/// <summary>
        
/// 查找标签或创建标签
        
/// </summary>
        
/// <param name="tabs">工具箱的标签集合</param>
        
/// <param name="name">标签名称</param>
        
/// <param name="create">如果找不到,是否以查找名称为新的标签名称来进行创建</param>
        
/// <returns>查找到的标签对象或新建的标签对象</returns>

        private ToolBoxTab FindOrCreateTab(ToolBoxTabs tabs, string name, bool create)
        
{
            
if (tabs != null)
            
{
                
for (int i = 1; i <= tabs.Count; i++)
                
{
                    ToolBoxTab tab 
= tabs.Item(i);
                    
if (tab.Name == name)
                    
{
                        
return tab;
                    }

                }

                
if (create)
                
{
                    Console.WriteLine(
"创建工具箱标签[" + TABLABLE + "]");
                    
return tabs.Add(name);
                }

            }

            
return null;
        }


        
#endregion



三、改写Main方法,代码如下:

static   void  Main( string [] args)
        
{
            
try
            
{
                
if (Program.IsOpenVS())
                
{
                    Console.WriteLine(
"请关闭VS2005!");
                }

                
else
                
{
                    Type typeFromProgID 
= Type.GetTypeFromProgID("VisualStudio.DTE.8.0"false);
                    DTE myDTE 
= (DTE)Activator.CreateInstance(typeFromProgID);

                    
if (myDTE == null)
                    
{
                        Console.WriteLine(
"无法打开DTE!");
                        
return;
                    }


                    MessageFilter.Register();

                    
try
                    
{
                        ToolBoxCreator creator 
= new ToolBoxCreator();
                        creator.RunCreator(myDTE);
                    }

                    
catch
                    
{
                        
throw;
                    }

                    
finally
                    
{
                        myDTE.Quit();
                        MessageFilter.Revoke();
                    }

                }

            }

            
catch (Exception ex)
            
{
                Console.WriteLine(ex.Message);
            }
  

           Console.Read();
        }

IsOpenVS()方法用来判断VS2005是否启动,如果启动,注册控件到工具箱将不会成功!

/// <summary>
        
/// 是否打开VS2005
        
/// </summary>
        
/// <returns></returns>

         public   static   bool  IsOpenVS()
        
{
            
foreach (System.Diagnostics.Process process in System.Diagnostics.Process.GetProcesses())
            
{
                
if (process.ProcessName == "devenv")
                
{
                    
return true;
                }

            }

            
return false;
        }

接下就启动DTE,如果成功则进行消息过滤器注册,这样主要为了避免程序在进行注册时发生中断。过滤器实现IMessageFilter接口,为了避免与System.Windows.Form.IMessageFilter接口重名,这里改作IOleMessageFilter:

     /// <summary>
    
/// 用来处理当前线程的并发事件,只有一个消息过滤器能够注册到单线程中,多线程没有消息过滤器
    
/// <remarks>
    
/// MessageFilter:消息过滤器
    
/// </remarks>
    
/// </summary>

    [ComImport, Guid( " 00000016-0000-0000-C000-000000000046 " ), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    
internal   interface  IOleMessageFilter
    
{
        [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);
    }

}

实现类:
     /// <summary>
    
/// 消息过滤器类
    
/// </summary>

     internal   class  MessageFilter : IOleMessageFilter
    
{
        
/// <summary>
        
/// 向OLE 注册登记 IOleMessageFilter(IMessageFilter) 实例
        
/// </summary>
        
/// <param name="newfilter">将被注册到当前线程中的消息过滤器</param>
        
/// <param name="oldfilter">以前注册到当前线程中的消息过滤器,如果没有则为NULL</param>
        
/// <returns>
        
/// S_OK 注册或取消注册成功;
        
/// S_FALSE 注册或取消注册失败。
        
/// </returns>

        [DllImport("Ole32.dll")]
        
private static extern int CoRegisterMessageFilter(IOleMessageFilter newfilter, out IOleMessageFilter oldfilter);

        
/// <summary>
        
/// 注册消息过滤器
        
/// </summary>

        public static void Register()
        
{
            IOleMessageFilter newfilter 
= new MessageFilter();
            IOleMessageFilter oldfilter 
= null;
            CoRegisterMessageFilter(newfilter, 
out oldfilter);
        }


        
/// <summary>
        
/// 取消注册
        
/// </summary>

        public static void Revoke()
        
{
            IOleMessageFilter oldfilter 
= null;
            CoRegisterMessageFilter(
nullout oldfilter);
        }


        
/// <summary>
        
/// 
        
/// </summary>
        
/// <param name="dwCallType"></param>
        
/// <param name="hTaskCaller"></param>
        
/// <param name="dwTickCount"></param>
        
/// <param name="lpInterfaceInfo"></param>
        
/// <returns>
        
/// SERVERCALL_ISHANDLED 
        
/// SERVERCALL_REJECTED 
        
/// SERVERCALL_RETRYLATER
        
/// </returns>

        int IOleMessageFilter.HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo)
        
{
            
return 0;//SERVERCALL_ISHANDLED
        }


        
/// <summary>
        
/// 当COM等待远程调用回复的时候,有Windows消息出现在COM应用程序消息队列中时调用
        
/// </summary>
        
/// <param name="hTaskCallee"></param>
        
/// <param name="dwTickCount"></param>
        
/// <param name="dwPendingType"></param>
        
/// <returns>
        
/// PENDINGMSG_CANCELCALL 
        
/// PENDINGMSG_WAITNOPROCESS
        
/// PENDINGMSG_WAITDEFPROCESS
        
/// </returns>

        int IOleMessageFilter.MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType)
        
{
            
return 2;//PENDINGMSG_WAITDEFPROCESS 
        }


        
/// <summary>
        
/// 
        
/// </summary>
        
/// <param name="hTaskCallee"></param>
        
/// <param name="dwTickCount"></param>
        
/// <param name="dwRejectType">SERVERCALL_REJECTED 或 SERVERCALL_RETRYLATER</param>
        
/// <returns>
        
/// -1                      取消调用
        
/// Value >= 0 & &lt 100    立即重试
        
/// Value >= 100            等待Value毫秒再重新调用
        
/// </returns>

        int IOleMessageFilter.RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType)
        
{
            
if (dwRejectType == 2) //SERVERCALL_RETRYLATER
            {
                
return 99;          //如果返回值>=0 & <100 立即重试
            }

            
return -1;              //取消调用
        }

    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值