views:

497

answers:

4

I would like to open into memory an existing .sln file.

Example of a non-working method:

private Solution2 OpenSolution(string filePath)
{
    Solution2 sln;
    sln.Open(filePath);
    return sln;
}

If I have an instance of Solution2 then i can call the method Open; but how can i get an instance of Solution2?

My goal is then to get the adequate project and read some of its settings... but that's easy having access to the solution.

Thanks in advance, Luís

A: 

Solution2 et al are basically parts of Visual Studio SDK, which you'd have to redistribute with your application (with all the licensing implications).

Since .sln files are plain old XML, you can always open it in XmlDocument and then XPath into it.

Anton Gogolev
I really want to access the .sln file as a Solution2 instance. I then want to be able to use the methods already provided by Visual Studio developers
Luis Filipe
.sln are not XML. .proj are XML-Files
Jehof
A: 

I don't have much experience with this, but try this msdn article. It isn't directly what you are looking for but they do instantiate a solution2 object in the sample code.

Chris Thompson
Hej! Thanks for your answer but unfortunately is does not help me in this particular situation.In the example they already have a DTE instance and from it they get the Solution instance.I'm getting the feeling that it's just impossible to do what i'd like to... maybe there's some reason to it due to some VS inner works
Luis Filipe
+2  A: 

You can programmatically create a hidden instance of Visual Studio, and then use it to manipulate your solution. This example will list out all the projects that live in the given solution.

using System;
using System.Runtime.InteropServices;
using EnvDTE;
using EnvDTE80;

namespace so_sln
{
   class Program
   {
      [STAThread]
      static void Main(string[] args)
      {
         System.Type t = System.Type.GetTypeFromProgID("VisualStudio.DTE.8.0", true);
         DTE2 dte = (EnvDTE80.DTE2)System.Activator.CreateInstance(t, true);

         // See http://msdn.microsoft.com/en-us/library/ms228772.aspx for the
         // code for MessageFilter - just paste it into the so_sln namespace.
         MessageFilter.Register();

         dte.Solution.Open(@"C:\path\to\my.sln");
         foreach (Project project in dte.Solution.Projects)
         {
            Console.WriteLine(project.Name);
         }

         dte.Quit();
      }
   }

   public class MessageFilter : IOleMessageFilter
   {
      ... Continues at http://msdn.microsoft.com/en-us/library/ms228772.aspx

(The nonsense with STAThread and MessageFilter is "due to threading contention issues between external multi-threaded applications and Visual Studio", whatever that means. Pasting in the code from http://msdn.microsoft.com/en-us/library/ms228772.aspx makes it work.)

RichieHindle
Great, It works!
Luis Filipe
+1  A: 

Solution2 is an interface, not a class. You cannot directly make an object of type Solution2, only reference objects as a Solution2 that contain the Solution2 interface.

As far as I'm aware, classes that implement the Solution2 interface are only available as part of the interface collection in the Visual Studio integration, so you will have to do something similar to what RichieHindle mentions, and create a new hidden Visual Studio instance to load the solution.

If you are just wanting to grab a couple settings out of the sln file, I'd potentially recommend parsing it yourself, the file format is pretty simple. If you are trying to pull a setting out, chances are the odd edge case where parsing the sln yourself wouldn't work also wouldn't work with what you are trying to do if Visual Studio parsed the sln for you.

Drakonite