和我一起学VSTA(Visual Studio Tools for Applications )(四)

前三篇简单介绍了VSTA的用途以及开发前期准备,这一篇将介绍具体的开发。

我们先实现一个最简单的功能,打开VSTA IDE编程环境。

首先在VSTASAMPLE项目中,添加如下引用:

 

 

以及:

  • Microsoft Development Enviroment 8.0.

  • DTEProvider 1.0 Type Library

     

    添加HostItemProvider.cs,代码如下:

     

     1using System;
     2using System.Collections.Generic;
     3using System.Text;
     4using System.AddIn.Contract;
     5using System.AddIn.Contract.Automation;
     6using System.Runtime.Remoting;
     7using Microsoft.VisualStudio.Tools.Applications.Contract;
     8using Microsoft.VisualStudio.Tools.Applications;
     9
    10namespace VSTASample
    11{
    12    internal class HostItemProvider : ContractAdapterBase,
    13    IHostItemProviderContract
    14    {
    15        private VSTAApplication application;
    16
    17        public HostItemProvider( VSTAApplication application,
    18            TypeInfrastructureManager typeInfrastructureManager )
    19            : base(typeInfrastructureManager)
    20        {
    21            this.application = application;
    22        }

    23
    24        protected override IContract QueryContract( string contractId )
    25        {
    26            if(String.Compare(contractId,
    27                typeof(IHostItemProviderContract).AssemblyQualifiedName,
    28                StringComparison.Ordinal) == 0)
    29            {
    30                return (IContract)this;
    31            }

    32
    33            return base.QueryContract(contractId);
    34        }

    35
    36        public IRemoteObjectContract GetHostObject( string objectType, string cookie )
    37        {
    38            if(String.Compare(objectType,
    39                typeof(RCS.Common.VSTA.VSTAApplication).FullName,
    40                StringComparison.Ordinal) == 0)
    41            {
    42                RemoteObjectAdapter adapter = new RemoteObjectAdapter(
    43                    typeof(RCS.Common.VSTA.VSTAApplication),
    44                    application, TypeInfrastructureManager);
    45                return adapter;
    46            }

    47
    48            throw new ArgumentOutOfRangeException();
    49        }

    50
    51        protected override string RemoteToString()
    52        {
    53            return this.ToString();
    54        }

    55
    56        protected override int GetRemoteHashCode()
    57        {
    58            return this.GetHashCode();
    59        }

    60
    61        protected override bool RemoteEquals( IContract contract )
    62        {
    63            if(contract == null)
    64                return false;
    65
    66            if(!System.Runtime.Remoting.RemotingServices.
    67                IsObjectOutOfAppDomain(contract))
    68            {
    69                HostItemProvider contractAdapter =
    70                    contract as HostItemProvider;
    71                return this.Equals(contractAdapter);
    72            }

    73
    74            return false;
    75        }

    76    }

    77}

    78

     添加一个IDEManagement.cs,代码如下:

     

      1using System;
      2using System.Collections.Generic;
      3using System.Text;
      4using System.Reflection;
      5using System.Windows.Forms;
      6using Microsoft.VisualStudio.Tools.Applications;
      7using Microsoft.VisualStudio.Tools.Applications.Contract;
      8using Microsoft.VisualStudio.Tools.Applications.DesignTime.Interop;
      9using System.AddIn.Contract.Automation;
     10using EnvDTE80;
     11using VSTADTEProvider.Interop;
     12using System.IO;
     13using System.Collections;
     14using EnvDTE;
     15
     16namespace VSTASample
     17{
     18    /// <summary>
     19    /// VSTA操作方法类
     20    /// </summary>

     21    internal partial class IDEManagement
     22    {
     23        private VSTAApplication application;
     24        //private Context macroContext;
     25        //private AddInCollection addInCollection;
     26        private IHostItemProviderContract itemProvider;
     27        private TypeInfrastructureManager typeInfrastructureManager;
     28        private EnvDTE.DTE vstaDTE;
     29        private EnvDTE.Project macroProject; 
     30        //private IEntryPointContract[] hostItems;
     31        private string hostID;
     32        private string templateName;
     33
     34        /// <summary>
     35        /// 初始化Extension类的新实例。
     36        /// </summary>

     37        internal IDEManagement()
     38        {
     39            InitializeTypeInfrastructureManager();
     40        }

     41
     42        
     43        internal void Connect(VSTAApplication application, string hostID,string templateName)
     44        {
     45            this.application = application;
     46            this.application.IDEManagement = this;
     47            this.hostID = hostID;
     48            this.templateName = templateName;
     49
     50            this.itemProvider = new HostItemProvider(application,TypeInfrastructureManager);
     51            //this.macroPath = @"C:\ShapeAppSamples\MyVSTADLLTest\Macros\bin";
     52            //LoadAddIns();
     53            //InitializeMenus();
     54
     55        }
      
     56        
     57       Internal Properties
     67
     68        /// <summary>
     69        /// 打开脚本编程环境
     70        /// </summary>
     71        /// <param name="projectDirectory">脚本程序所在目录</param>
     72        /// <param name="projectFilename">脚本程序工程文件名称(*.vbproj)</param>
     73        /// <returns></returns>

     74        public bool StartIDE(string projectDirectory, string projectFilename)
     75        {
     76            EnsureIDE(hostID);
     77            if (vstaDTE.MainWindow.Visible)
     78            {
     79                //vstaDTE.MainWindow.Activate();
     80                vstaDTE.MainWindow.SetFocus();
     81                return true;
     82            }

     83            else
     84            {
     85                vstaDTE.MainWindow.Visible = true;
     86                vstaDTE.MainWindow.WindowState = EnvDTE.vsWindowState.vsWindowStateMaximize;
     87                string projectFilePath = System.IO.Path.Combine(projectDirectory, projectFilename);
     88                if (System.IO.File.Exists(projectFilePath))
     89                {
     90                    OpenMacroProject(projectFilePath);
     91                }

     92                else
     93                {
     94                    try
     95                    {
     96                        CreateNewMacroProject(projectDirectory, projectFilename);
     97                    }

     98                    catch(Exception e)
     99                    {
    100                        MessageBox.Show(
    101                            e.Message,
    102                            hostID, MessageBoxButtons.OK, MessageBoxIcon.Error);
    103                        this.vstaDTE.Quit();
    104                        vstaDTE = null;
    105                        return false;
    106                    }

    107                }

    108                return true;
    109            }

    110        }

    111
    112        private void EnsureIDE(string hostID)
    113        {
    114            if (this.vstaDTE == null)
    115            {
    116                try
    117                {
    118                    IDTEProvider dteProvider = new VSTADTEProviderClass();
    119                    //string HostID = "MyVSTADLLTest";
    120                    UInt32 TimeOut = 10000;
    121                    vstaDTE = dteProvider.GetDTE(hostID, TimeOut);
    122                    System.Diagnostics.Debug.Assert(this.vstaDTE != null);
    123                }

    124                catch
    125                {
    126                    // If DTEProvider does not work, try co-creating DTE instead.
    127                    object objDTE = new EnvDTE.DTE();
    128                    this.vstaDTE = (EnvDTE.DTE)objDTE;
    129                }

    130
    131                //vstaDTE.MainWindow.Visible = true;
    132                //增加关闭IDE窗口时关闭vsta.exe进程以及编译
    133                EnvDTE.CommandEvents commandEvents = vstaDTE.Events.get_CommandEvents("{00000000-0000-0000-0000-000000000000}"0);
    134
    135                commandEvents.BeforeExecute += new EnvDTE._dispCommandEvents_BeforeExecuteEventHandler(commandEvents_BeforeExecute);
    136
    137                //get and subscribe to the File.Exit event prior to execution
    138                EnvDTE.CommandEvents exitCommand = vstaDTE.Events.get_CommandEvents("{5EFC7975-14BC-11CF-9B2B-00AA00573819}"229);
    139
    140                exitCommand.BeforeExecute += new EnvDTE._dispCommandEvents_BeforeExecuteEventHandler(exitCommand_BeforeExecute);
    141            }

    142        }

    143
    144        /// <summary>
    145        /// 关闭IDE
    146        /// </summary>

    147        public void ExitIDE()
    148        {
    149            if(this.vstaDTE != null)
    150            {
    151                if(this.vstaDTE.Mode == EnvDTE.vsIDEMode.vsIDEModeDebug)
    152                {
    153                    this.vstaDTE.Debugger.Stop(true);
    154                }

    155                this.macroProject.Save(null);
    156                this.vstaDTE.Quit();
    157            }

    158         private void CreateNewMacroProject(string projectDirectory, string projectFileName)
    159        {
    160            Solution2 sol = (Solution2)vstaDTE.Solution;
    161            //string projectTemplatePath = @"C:\ShapeAppSamples\VSTATest\templates\VisualBasic\1033\";
    162            string projectTemplatePath = sol.GetProjectTemplate(templateName, "VisualBasic");
    163            //string targetProjectDirectory = @"C:\ShapeAppSamples\MyVSTADLLTest\Macros";
    164            //string targetProjectFilename = "MyEventSampleMacro.vbproj";
    165
    166            this.vstaDTE.Solution.AddFromTemplate(projectTemplatePath,projectDirectory, projectFileName, true);
    167            this.vstaDTE.Solution.SolutionBuild.Build(true);
    168        }

    169        
    170        private void OpenMacroProject(string projectFilePath)
    171        {
    172            //string projectFilePath = @"C:\ShapeAppSamples\MyVSTADLLTest\Macros\MyEventSampleMacro.vbproj";
    173            this.macroProject = this.vstaDTE.Solution.AddFromFile(projectFilePath, true);
    174            //vstaDTE.MainWindow.Visible = true;
    175        }

    176
    177        EnvDTE.CodeElement FindCodeElementInCodeElements(EnvDTE.CodeElements codeElems, EnvDTE.vsCMElement kind, string fullName)
    178        {
    179            foreach (EnvDTE.CodeElement codeElem in codeElems)
    180            {
    181                if (codeElem.Kind == kind)
    182                {
    183                    if (codeElem.FullName == fullName)
    184                    {
    185                        if (codeElem.Kind == EnvDTE.vsCMElement.vsCMElementFunction)
    186                        {
    187                            EnvDTE.CodeFunction codeFunc = (EnvDTE.CodeFunction)codeElem;
    188                            if (codeFunc.IsOverloaded)
    189                            {
    190                                if (codeFunc.Parameters.Count != 0)
    191                                {
    192                                    continue;
    193                                }

    194                            }

    195                        }

    196
    197                        return codeElem;
    198                    }

    199                }

    200            }

    201
    202            return null;
    203        }

    204        private void exitCommand_BeforeExecute( string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault )
    205        {
    206            //Project.IsDirty is always false, so use .Saved which starts true
    207            if(this.macroProject.Saved == true)
    208            {
    209                //prompt the user to save the project
    210                this.macroProject.Save(null);
    211                //change the saved state
    212                this.macroProject.Saved = false;
    213
    214                this.vstaDTE.Solution.SolutionBuild.Build(true);
    215            }

    216
    217            //quit the IDE
    218            this.vstaDTE.Quit();
    219
    220            this.vstaDTE = null;
    221        }

    222
    223        private void commandEvents_BeforeExecute( string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault )
    224        {
    225            EnvDTE.Command objCommand = default(EnvDTE.Command);
    226            //string sCommandName = null;
    227
    228            //break here to check out any commands you are interested in
    229            objCommand = vstaDTE.Commands.Item(Guid, ID);
    230
    231            //if((objCommand != null))
    232            //{
    233            //    sCommandName = objCommand.Name;
    234
    235            //    if(sCommandName.Equals("Something.WorthWatching"))
    236            //    {
    237            //        //do something
    238            //    }
    239            //}
    240
    241        }

    242        private void InitializeTypeInfrastructureManager()
    243        {
    244            if (typeInfrastructureManager == null)
    245            {
    246                typeInfrastructureManager = new TypeInfrastructureManager();
    247
    248                // This was auto-generated from ProxyGen with the /h:hostmapfile commandline argument.
    249
    250                global::System.Type hostType;
    251                global::System.Type proxyType;
    252
    253
    254                                hostType = typeof(global::VSTASample.VSTAApplication);
    255                proxyType = typeof(NonProxiableType<global::VSTASample.VSTAApplication>);
    256                typeInfrastructureManager.CanonicalNameToTypeMap.Add("VSTASample, VSTASample.VSTAApplication", proxyType);
    257                typeInfrastructureManager.TypeToCanonicalNameMap.Add(hostType, "VSTASample, VSTASample.VSTAApplication");
    258            }

    259       }

    260  }

    261}

    这里,我们为了方便不同的项目调用,用一个操作类来发布,添加一个VSTAHelper.cs,代码如下:

     

      1using System;
      2using System.Collections.Generic;
      3using System.Text;
      4using System.Reflection;
      5using EnvDTE;
      6using System.Collections;
      7
      8namespace VSTASample
      9{
     10    /// <summary>
     11    /// VSTA操作类
     12    /// </summary>

     13    public class VSTAHelper
     14    {
     15        private static VSTAHelper instance;
     16
     17        /// <summary>
     18        /// VSTAHelper类单一实例
     19        /// </summary>

     20        public static VSTAHelper Instance
     21        {
     22            get
     23            {
     24                if(VSTAHelper.instance == null)
     25                {
     26                    VSTAHelper.instance = new VSTAHelper();
     27                }

     28
     29                return VSTAHelper.instance;
     30            }

     31        }

     32
     33        private VSTAApplication app;
     34        /// <summary>
     35        /// 初始化类的实例。
     36        /// </summary>

     37        private VSTAHelper()
     38        {
     39            {
     40                app = new VSTAApplication();
     41            }

     42        }

     43
     44        /// <summary>
     45        /// 打开脚本编程环境
     46        /// </summary>
     47        /// <returns></returns>
     48        /// <param name="projectDirectory">脚本程序所在目录(如:C:\ShapeAppSamples\MyVSTADLLTest\Macros)</param>
     49        /// <param name="projectFilename">脚本程序工程文件名称(*.vbproj)</param>
     50        /// <example><code>
     51        /// private VSTAHelper vstaHelper = new VSTAHelper();
     52        /// vstaHelper.StartIDE(@"..\Solutions\自动计量\script\Demo","Demo.vbproj");
     53        /// </code></example>

     54        public void StartIDE( string projectDirectory, string projectFilename )
     55        {
     56            //using(MessageFilter messageFilter = new MessageFilter())
     57            {
     58                app.IDEManagement.StartIDE(projectDirectory, projectFilename);
     59            }

     60        }

     61
     62        /// <summary>
     63        /// 关闭IDE
     64        /// </summary>
     65        /// <example><code>
     66        /// private VSTAHelper vstaHelper = new VSTAHelper();
     67        /// vstaHelper.ExitIDE();
     68        /// </code></example>

     69        public void ExitIDE()
     70        {
     71            app.IDEManagement.ExitIDE();
     72        }

     73
     74    }

     75    internal partial class VSTAApplication
     76    {
     77        private IDEManagement ideManagement;
     78        /// <summary>
     79        /// 操作方法类
     80        /// </summary>

     81        public IDEManagement IDEManagement
     82        {
     83            get
     84            {
     85                if(this.ideManagement == null)
     86                {
     87                    ideManagement = new IDEManagement();
     88                    ideManagement.Connect(this"VSTAHelper""dlladdin.zip");
     89                }

     90                return ideManagement;
     91            }

     92            set
     93            {
     94                ideManagement = value;
     95            }

     96        }

     97
     98    }

     99}

    100

    编译生成。

    下面就是新建个winform项目,使用操作类即可。

    VSTASample.VSTAHelper.Instance.StartIDE(projectPath,projectFileName);

  • posted @ 2009-06-22 17:10  秋水萧萧  阅读(3153)  评论(2编辑  收藏  举报