Click here to Skip to main content
15,886,724 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010

Project
("{00000000-0000-0000-0000-000000000000}") = "Test Projects", "TestProjects", "{5FAF487E-B913-4D46-983E-CB13FDF36FCB}" 
EndProject

Project
("{11111111-1111-1111-1111-111111111111}")= "ProjPropHelperAPI", "ProjPropHelperAPI\ProjPropHelperAPI.vcxproj", "{22222222-2222-2222-2222-222222222222}" 
EndProject 

Project
("{33333333-3333-3333-3333-333333333333}") = "ProjectPropertiesHelperAPI", "ProjectPropertiesHelperAPI\ProjectPropertiesHelperAPI.csproj", "{66666666-6666-6666-6666-666666666666}"     
    ProjectSection(ProjectDependencies) = postProject         
    {44444444-4444-4444-4444-444444444444} = {44444444-4444-4444-4444-444444444444}    
    {55555555-5555-5555-5555-555555555555} = {55555555-5555-5555-5555-555555555555}
    EndProjectSection 
EndProject 


I can read the Project Names, their GUIDs and Paths using the solution mentioned in this answer. The name, guid and path is accessed using

C#
Type.GetType().GetProperty("ProjectGuid", BindingFlags.NonPublic | BindingFlags.Instance); 


I need to parse the ProjectDependencies Tab shown in the above .sln extract. I want to know if the ProjectDependencies values can be obtained similar to ProjectName, ProjectGuid and RelativePath properties?

P.S. Well, I dont really mind as long as I get the project dependencies, by whatever means (not necessarily by Reflection as shown in the c# snippet above). Any ideas are welcome.

Thanks in advance!!
Posted
Updated 7-Sep-12 5:07am
v4

There are can be at least two completely different things which may give different results. It depends on what you really need. (It's a good idea to start all questions from explanation of your ultimate purpose.)

First one is: you can extract dependency information as it is prescribed in the solution file. This does not reflect real dependency, it only shows what the author of the solution thinks what should depend on what (plus dependencies Visual Studio was able to figure out automatically). This way does not require the projects to be built, and you don't need the target assemblies to be in place. To do it, all you need is just the ability to parse simple data from text (a text of a .SLN file) and apply some logic. You can create few different solutions for samples, to see how the file is structured. Unlike XML-based MSBuild project file format, the format of the .SLN files is not really documented. [EDIT] Even though the .SLN file format is probably not documented, you can use access data not directly, but using the solution document interface EnvDTE80.Solution2; please see Solution 2. [END EDIT]

The second thing is: you can build all the solution (so you will need all projects to be buildable) and perform the analysis of dependencies based on the compiled binary assemblies using Reflection. This is a pretty simple thing. Here is what you need:
Load some assembly to be analyzed based on the file name of its main executable module:
http://msdn.microsoft.com/en-us/library/1009fa28.aspx[^].

When this is done, obtain all referenced assemblies:
http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getreferencedassemblies.aspx[^].

For each referenced assembly, load it using the assembly name object obtained for each referenced assembly on the previous step:
http://msdn.microsoft.com/en-us/library/system.reflection.assemblyname.aspx[^].

Load each of referenced assemblies by their respective instanced of System.Reflection.AssemblyName:
http://msdn.microsoft.com/en-us/library/x4cw969y.aspx[^].

Do it all recursively to produce the whole dependency graph. Easy enough.

—SA
 
Share this answer
 
v3
Comments
Espen Harlinn 7-Sep-12 19:03pm    
5'ed!
Sergey Alexandrovich Kryukov 7-Sep-12 19:19pm    
Thank you, Espen.
--SA
Apart from what Sergey mentions, you could look at the
Solution2 interface[^] and the Project interface[^]

Controlling Projects and Solutions[^]

It's a lot of info to wade through, but what you're looking for is there somewhere.

Best regards
Espen Harlinn
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 7-Sep-12 19:24pm    
Ah, you've fixed my answer where I failed to advise using solution interface. Of course, my 5.
--SA
Espen Harlinn 8-Sep-12 6:15am    
Thank you, Sergey :-D
If you go parsing the files, you may do the following:

  1. parse the sln file for all Project...ProjectEnd entries
  2. from these entries take the GUID and the path (if it ends on \.\w+proj)
  3. from these entries also take the ProjectSection(ProjectDependencies) = postProject (if it exists and store the contained GUIDs as dependencies)
  4. parse each proj file for <ProjectReference>...</ProjectReference> and take all contained <Project>...</Project> entries as GUID to the dependent project
  5. do a topological sort on the dependencies


The steps above respect the fact that Visual Studio may store dependency information at two locations: in the solution and in the project file. It also takes care of the fact that some project entries in the sln file are not real projects (they may be folders and solution items).

For the DAG/topological sort, see Directed Acyclic Graphs[^]

Cheers
Andi
 
Share this answer
 
v2
Here is what i did...

C#
var filePath = @"C:\Users\xyz\Documents\Visual Studio 2010\Projects\test\test.sln"         
var slnLines = File.ReadAllLines(filePath);      
var projGuid = new List<string>();         

for(var i=0; i<slnlines.length;)
{             
    if (slnLines[i].Contains(@"ProjectSection(ProjectDependencies)"))                 
        while (!slnLines[i+1].Contains("EndProjectSection"))
        {                     
            var temp = (slnLines[i+1].Split(new[]{'=', '\n', '\t', ' '},2,StringSplitOptions.RemoveEmptyEntries));
            if(temp.ElementAt(0) == temp.ElementAt(1))
                projGuid.Add(temp.ElementAt(0));
            i++;
        }
}

using (var file = new StreamWriter(@"C:\Users\xyz\Desktop\Results.txt"))
{
    foreach (var pGuid in projGuid)
    {
        file.WriteLine(pGuid);
    }
}


Thanks!!
 
Share this answer
 
v2
Comments
Andreas Gieriet 10-Sep-12 14:58pm    
That will only catch the explicitly set dependencies. There are also dependencies defined within the project files: dependencies by adding a reference to a sibling project of the solution (they do not appear in the above mentioned dependency list).
Cheers
Andi
PS: I did fix some formatting in your code example (replacing the < and > by &lt; and &gt;).
aromore 10-Sep-12 15:24pm    
@andreas: Thanks fr the edits!!

D u mean the references indicated as <ProjectReference> in the .csproj file?
Andreas Gieriet 10-Sep-12 16:11pm    
Yes. See my solution #3. You don't get the overal dependency sequence by simply collecting the individual dependencies - you need to do a topological sort on the collected data (in order to get a build sequence).
E.g. make a solution with 4 csproj files (app, lib, apptest, libtest), include proj references in
- app --> lib
- apptest --> app
- apptest --> lib
- libtest --> lib
Save all.
You will not see any dependency list in the sln file.
If you inspect the dependency list from within VS2010, you will see correct dependencies, and a meaningful build sequence.
Cheers
Andi

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900