locked
Get current environment name for DTE reference RRS feed

  • Question

  • Ok, I am getting a reference to the DTE2 object by using the following code.
    // Get an instance of the currently running Visual Studio IDE.
    EnvDTE80.DTE2 dte2;
    dte2 = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.
    GetActiveObject("VisualStudio.DTE.10.0");
    
    This works great but, I want to know if there is a way to determine the "VisualStudio.DTE.8.0" part dynamically? 
    I would like to be able to have the code determine what version of the IDE is being used.

    Best and TIA!

    Ryan

    Monday, January 3, 2011 5:55 PM

Answers

  • You can enumerator the RunningObjectTable (ROT), which is where GetActiveObject is locating the object.  Some code to do so (in a console application) is below

    namespace ROTEnum
    {
      using System;
      using System.Runtime.InteropServices;
      using System.Runtime.InteropServices.ComTypes;
    
      class Program
      {
        [DllImport("ole32.dll")]
        public static extern int GetRunningObjectTable(uint dwReserved, out IRunningObjectTable pprot);
    
        [DllImport("ole32.dll")]
        public static extern int CreateBindCtx(uint dwReserved, out IBindCtx ppbc);
    
        static void Main(string[] args)
        {
          IRunningObjectTable rot;
          Marshal.ThrowExceptionForHR(GetRunningObjectTable(0 /*reserved*/, out rot));
    
          IEnumMoniker enumerator;
          rot.EnumRunning(out enumerator);
    
          IMoniker[] monikers = new IMoniker[1];
          enumerator.Reset();
    
          IBindCtx bindCtxt;
          Marshal.ThrowExceptionForHR(CreateBindCtx(0 /*reserved*/, out bindCtxt));
    
          while (enumerator.Next(1, monikers, IntPtr.Zero) == 0)
          {
            string displayName;
            monikers[0]. GetDisplayName(bindCtxt, null, out displayName);
    
            Console.WriteLine(String.Format("Moniker - {0}{1}", displayName, Environment.NewLine));
          }
        }
      }
    }
    

    On my system the interesting output is

    Moniker - !VisualStudio.DTE.10.0:2564
    Moniker - !VisualStudio.DTE.10.0:6632
    Moniker - !VisualStudio.DTE.10.0:3884

    I have multiple instances of VS runnning and the appended number is the PID of each instance.  If you just call GetActiveObject without specifying the PID I believe it will return the first one it finds.  Theoretically users could be running multiple instances (and versions) of VS, so doing stuff via DTE out of proc in such a case can be tricky as you need to operate against the right instance.

    Ryan

    Monday, January 3, 2011 8:30 PM
  • Yes, DTE is an object that allows you to interact with a SPECIFIC instance of VS (since it exposes things like solutions, projects, commands).  If there are more than one instances running then there are more than one instances of the DTE object in the ROT.  If you just grab an arbitrary one then whatever actions you perform against it may or may not be against the 'right' instance in the user's mind.

    A simple solution could be if you identify more than one you can get the DTE object for each instance, get the Solution object from each DTE instance, get the display name/caption of the solution and then have the user pick which instance they wanted to target, something like a dialog that displayed


    VS instance 1 - Foo Solution

    VS instance 2 - Bar Solution

     

    If you only found one DTE object then you don't have to explicitly choose anything as there is only one possible 'target', but if there is more than one it would be impossible for you to tell which one the user was trying to target with your tool, you would need them to clarify.


    Ryan

    • Marked as answer by rkbrown Monday, January 3, 2011 9:24 PM
    Monday, January 3, 2011 8:56 PM

All replies

  • You can enumerator the RunningObjectTable (ROT), which is where GetActiveObject is locating the object.  Some code to do so (in a console application) is below

    namespace ROTEnum
    {
      using System;
      using System.Runtime.InteropServices;
      using System.Runtime.InteropServices.ComTypes;
    
      class Program
      {
        [DllImport("ole32.dll")]
        public static extern int GetRunningObjectTable(uint dwReserved, out IRunningObjectTable pprot);
    
        [DllImport("ole32.dll")]
        public static extern int CreateBindCtx(uint dwReserved, out IBindCtx ppbc);
    
        static void Main(string[] args)
        {
          IRunningObjectTable rot;
          Marshal.ThrowExceptionForHR(GetRunningObjectTable(0 /*reserved*/, out rot));
    
          IEnumMoniker enumerator;
          rot.EnumRunning(out enumerator);
    
          IMoniker[] monikers = new IMoniker[1];
          enumerator.Reset();
    
          IBindCtx bindCtxt;
          Marshal.ThrowExceptionForHR(CreateBindCtx(0 /*reserved*/, out bindCtxt));
    
          while (enumerator.Next(1, monikers, IntPtr.Zero) == 0)
          {
            string displayName;
            monikers[0]. GetDisplayName(bindCtxt, null, out displayName);
    
            Console.WriteLine(String.Format("Moniker - {0}{1}", displayName, Environment.NewLine));
          }
        }
      }
    }
    

    On my system the interesting output is

    Moniker - !VisualStudio.DTE.10.0:2564
    Moniker - !VisualStudio.DTE.10.0:6632
    Moniker - !VisualStudio.DTE.10.0:3884

    I have multiple instances of VS runnning and the appended number is the PID of each instance.  If you just call GetActiveObject without specifying the PID I believe it will return the first one it finds.  Theoretically users could be running multiple instances (and versions) of VS, so doing stuff via DTE out of proc in such a case can be tricky as you need to operate against the right instance.

    Ryan

    Monday, January 3, 2011 8:30 PM
  • Ouch! Sounds like I may want another approach since, if I read correctly, if I get more than one vs moniker back I cannot determine which is the one I want.

    Thanks again for all the help!

    Monday, January 3, 2011 8:36 PM
  • Yes, DTE is an object that allows you to interact with a SPECIFIC instance of VS (since it exposes things like solutions, projects, commands).  If there are more than one instances running then there are more than one instances of the DTE object in the ROT.  If you just grab an arbitrary one then whatever actions you perform against it may or may not be against the 'right' instance in the user's mind.

    A simple solution could be if you identify more than one you can get the DTE object for each instance, get the Solution object from each DTE instance, get the display name/caption of the solution and then have the user pick which instance they wanted to target, something like a dialog that displayed


    VS instance 1 - Foo Solution

    VS instance 2 - Bar Solution

     

    If you only found one DTE object then you don't have to explicitly choose anything as there is only one possible 'target', but if there is more than one it would be impossible for you to tell which one the user was trying to target with your tool, you would need them to clarify.


    Ryan

    • Marked as answer by rkbrown Monday, January 3, 2011 9:24 PM
    Monday, January 3, 2011 8:56 PM
  • Ok, I can work with that. you rock!

    Thanks!

    Monday, January 3, 2011 9:24 PM