locked
Read/Write access to Reference properties RRS feed

  • Question

  • Hello,

    I wan't to have read/write access to CopyLocal property of some C# project references and to the list of this references. I'm using SlnHierarchTraversal sample as a basis (http://code.msdn.microsoft.com/SlnHierarchTraversal) for solution traversing. What should I do with particular assembly reference node to get access to its properties ? And how should I add/remove references to project ?

    Thanks in advance

    Monday, May 3, 2010 11:50 AM

Answers

  • Hi,

    1st:
    I don't know which VS Version you're using? I'm using VS2010, and I don't know if this works for 2008 as well!

    VSProject is defined in:
    Namespace:   VSLangProj
    Assembly:   VSLangProj (in VSLangProj.dll)
    You might need to add areference to your project.
    The docs are included in the VS2010 SDK you can add from online to your local help.

    To get all projects I use:

    public class MyPackage : Microsoft.VisualStudio.Shell.Package
    {
      ...
    
      /// <summary>
      /// Returns an enumeration with all Projects.
      /// </summary>
      /// <param name="flags">Specifies the projects to enumerate within a solution. For a list of grfEnumFlags values, see __VSENUMPROJFLAGS.</param>
      /// <param name="onlyThisTypeGuid">If the EPF_MATCHTYPE flag is specified, the enumerator iterates projects of this type only. Otherwise, this parameter is ignored.</param>
      /// <returns>Returns an enumeration of all projects</returns>
      public IEnumerable<IVsHierarchy> GetProjects(__VSENUMPROJFLAGS flags = __VSENUMPROJFLAGS.EPF_ALLPROJECTS, Guid onlyThisTypeGuid = new Guid())
      {
       IEnumHierarchies enumHierarchies;
       ErrorHandler.ThrowOnFailure(Solution.GetProjectEnum((uint)flags, onlyThisTypeGuid, out enumHierarchies));
       uint fetched = 1;
       IVsHierarchy[] hierarchies = new IVsHierarchy[10];
       while (fetched > 0)
       {
         ErrorHandler.ThrowOnFailure(enumHierarchies.Next(10, hierarchies, out fetched));
         for (int n = 0; n < fetched; ++n)
         {
          yield return hierarchies[n];
         }
       }
      }
    
      ...
    }

    You can paste this method simply into the Plugin Package class created by the VS2010 new plugin wizzard.
    I think the SolutionTraversal sample project is no plugin project? right.

    If you want to know if an IVsHierarchy node is a project you can query the property __VSHPROPID.VSHPROPID_TypeName.
    As far as I know only projects have this.

    • Marked as answer by AlexNG2 Wednesday, May 5, 2010 2:02 PM
    Tuesday, May 4, 2010 9:19 AM

All replies

  • Hi,

    you can use the VSProject interface which has a property called References.
    If you enumerate through it you get objects which implement the Reference interface, which has a read/write proiperty called CopyLocal.
    It's a bit tricky to get the VSProject interface starting from the IVsHierarchy, but the code below should work for this:

    IVSHierarchy vsHierarchy = (this is the project hierarch root node)
    
    // get EnvDTE.Project from hierarchy
    object pVar;
    vsHierarchy.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ExtObject, out pVar));
    var dteProject = pVar as EnvDTE.Project;
    
    // get the vsProject from dteProject
    var vsPrj = dteProject.Object as VSProject;
    
    // enumerate through references and set CopyLocal to fals
    foreach (Reference reference in vsPrj.References)
    {
      reference.CopyLocale = false;
    }

    I haven't actually tested this code, but it should work.

    btw. there might be an easier way to get the VsProject interface from IVsHierarchy, but I go the way above because I need the EnvDTE.Project anyway.

    Reinhard.

    Tuesday, May 4, 2010 5:58 AM
  • I tried this code using MS sample solution for hierarchy traversal. 1st, I don't know where to get VSProject - I looked through whole components collection (including Studio SDK, of course) and I can find only IVsProject which looks wrong. More than that, looks like

    var dteProject = pVar as EnvDTE.Project;

    always return non-null dteProject for many-many solution nodes while solution to be tested has only one project. Can System.__ComObject be EnvDTE.Project and give __ComObject to dteProject after casting ? I'm in doubts. I'm quite weak in .NET/COM interop which is highly required here. So this DOESN'T WORK for me.

    I can get Reference interface (VisualStudioIntegration\Common\IDL\vslangproj.idl, uuid 35D6FB50-35B6-4c81-B91C-3930B0D95386) for some solution tree nodes (I think they are correct ones), and already asked another thread how to invoke interface methods and get props :-) My current Marshal experiments like Marshal.GetObjectForIUnknown() give nothing interesting - I already have System.__ComObject, I need something better.

    Tuesday, May 4, 2010 8:15 AM
  • Hi,

    1st:
    I don't know which VS Version you're using? I'm using VS2010, and I don't know if this works for 2008 as well!

    VSProject is defined in:
    Namespace:   VSLangProj
    Assembly:   VSLangProj (in VSLangProj.dll)
    You might need to add areference to your project.
    The docs are included in the VS2010 SDK you can add from online to your local help.

    To get all projects I use:

    public class MyPackage : Microsoft.VisualStudio.Shell.Package
    {
      ...
    
      /// <summary>
      /// Returns an enumeration with all Projects.
      /// </summary>
      /// <param name="flags">Specifies the projects to enumerate within a solution. For a list of grfEnumFlags values, see __VSENUMPROJFLAGS.</param>
      /// <param name="onlyThisTypeGuid">If the EPF_MATCHTYPE flag is specified, the enumerator iterates projects of this type only. Otherwise, this parameter is ignored.</param>
      /// <returns>Returns an enumeration of all projects</returns>
      public IEnumerable<IVsHierarchy> GetProjects(__VSENUMPROJFLAGS flags = __VSENUMPROJFLAGS.EPF_ALLPROJECTS, Guid onlyThisTypeGuid = new Guid())
      {
       IEnumHierarchies enumHierarchies;
       ErrorHandler.ThrowOnFailure(Solution.GetProjectEnum((uint)flags, onlyThisTypeGuid, out enumHierarchies));
       uint fetched = 1;
       IVsHierarchy[] hierarchies = new IVsHierarchy[10];
       while (fetched > 0)
       {
         ErrorHandler.ThrowOnFailure(enumHierarchies.Next(10, hierarchies, out fetched));
         for (int n = 0; n < fetched; ++n)
         {
          yield return hierarchies[n];
         }
       }
      }
    
      ...
    }

    You can paste this method simply into the Plugin Package class created by the VS2010 new plugin wizzard.
    I think the SolutionTraversal sample project is no plugin project? right.

    If you want to know if an IVsHierarchy node is a project you can query the property __VSHPROPID.VSHPROPID_TypeName.
    As far as I know only projects have this.

    • Marked as answer by AlexNG2 Wednesday, May 5, 2010 2:02 PM
    Tuesday, May 4, 2010 9:19 AM
  • Hello, Alex

    Please use Reinhard Ostermeier's code, his code is perfect!

    If you use watch window to see a COM object, it will always be ystem.__ComObject.

    You don't need to Marshal it, var vsPrj = dteProject.Object as VSProject; will help you to get the VSProject COM Object, which will enable to get the references.

    Thanks

    Chao

    Wednesday, May 5, 2010 8:55 AM
  • Thanks to Reinhard. Yes, I'm using VS 2010. Referencing of VSLangProj solves so many my questions. As I understand, this assembly contains wrappers to VSLangProj.idl where all the necessary stuff sits.
    Wednesday, May 5, 2010 2:02 PM