0

VS has the "Project Dependencies" window but in a solution I work on there are over 100 projects. Trying to see all the dependencies of a specific project is time-consuming as you have to scroll through the entire list, and it's easy to miss one.

Is there a way just to list the dependencies, not all the projects with a tick-box showing which are dependencies?

Mr. Boy
  • 60,845
  • 93
  • 320
  • 589

2 Answers2

0

You may open a Visual Studio Solution file (.sln) in a text editor, for example, Notepad++. Once opened, search for ProjectSection(ProjectDependencies) = postProject within the specific project you are looking for.

The example of part of a .sln file below shows that the NativeUnitTest_CppDll project depends on NativeWin32CppDll project.

The only downside is that the dependencies are listed as GUIDs. You will have to do a text Find to locate their project names.

Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NativeWin32CppDll", "NativeWin32CppDll\NativeWin32CppDll.vcxproj", "{83FC3109-17DF-4B53-BCA0-F0DFC10AAE7F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NativeUnitTest_CppDll", "NativeUnitTest_CppDll\NativeUnitTest_CppDll.vcxproj", "{559CB21A-4763-4A1E-A70A-E8C656C53ED9}"
    ProjectSection(ProjectDependencies) = postProject
        {83FC3109-17DF-4B53-BCA0-F0DFC10AAE7F} = {83FC3109-17DF-4B53-BCA0-F0DFC10AAE7F}
    EndProjectSection
EndProject
Garland
  • 911
  • 7
  • 22
0

Could you please clarify: to see and list where? In the Visual Studio or some external tool? Just to see in a pop-up or to have an ability to copy the list?

I was trying to get those dependencies using Visual Studio's Solution object and its properties. There is a property named ProjectDependencies, but it was empty on my test, so I assume it is tracking auto-dependencies, not the one you specify manually.

Then I tried to get the list out of *.sln file, as was also suggested by gxy, in a simple console project (you should pass the solution file on a command line):

int main(int argc, char* argv[])
{
    if (argc != 2)
        return -1;
    ifstream sln(argv[1]);
    string line, name, guid;
    unordered_map<string, string> names;
    unordered_map<string, list<string>> dependencies;
    while (getline(sln, line))
    {
        if (line.find("Project(") == 0)
        {
            ParseProjGuid(line, name, guid);
            names[guid] = name;
            while (getline(sln, line))
            {
                if (line == "EndProject")
                    break;

                if (line.find("ProjectSection(ProjectDependencies)") != string::npos)
                {
                    while (getline(sln, line))
                    {
                        if (line.find("EndProjectSection") != string::npos)
                            break;
                        ParseDependGuid(line, guid);
                        dependencies[name].push_back(guid);
                    }
                }
            }
        }
    }
    for (auto d : dependencies)
    {
        cout << d.first << endl;
        for (auto g : d.second)
            cout << "\t" << names[g] << endl;
    }
    return 0;
}

I am using a couple of helper functions there:

string unquote(const string& s)
{
    if (s[0] == '"' && s[s.length() - 1] == '"')
        return s.substr(1, s.length() - 2);
    else
        return s;
}

void ParseProjGuid(const string& src, string& proj, string& guid)
{
    // Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "name", "path\name.vcxproj", "{9D4B97C3-1069-406C-973F-652706414C86}"
    size_t pos1 = src.find('=');
    size_t pos2 = src.find(',');
    size_t pos3 = src.rfind(',');
    proj = src.substr(pos1 + 1, pos2 - pos1 - 1);
    guid = src.substr(pos3 + 1);

    proj = trim(proj);
    guid = trim(guid);
    proj = unquote(proj);
    guid = unquote(guid);
}

void ParseDependGuid(const string& src, string& guid)
{
    // {165C1503-36B1-4577-9D99-3C1AFEBFC201} = {165C1503-36B1-4577-9D99-3C1AFEBFC201}
    size_t pos = src.find('=');
    guid = src.substr(0, pos);
    guid = trim(guid);
}

As well as trim function borrowed from from What's the best way to trim std::string?:

// trim from start
static inline string &ltrim(string &s) {
    s.erase(s.begin(), find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
    return s;
}

// trim from end
static inline string &rtrim(string &s) {
    s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
    return s;
}

// trim from both ends
static inline string &trim(string &s) {
    return ltrim(rtrim(s));
}

As my hobby is writing Visual Studio extensions, I have a question: do you think it will be a useful tool?

Community
  • 1
  • 1
Vlad Feinstein
  • 10,960
  • 1
  • 12
  • 27
  • Hey, thanks for taking the time on that! In an ideal world in VS itself, I just want to be able to select any project in the solution from a drop-list and see a list of its dependencies - similar to the Project Dependencies window but only showing the dependencies in the list, not a checklist of _all_ projects. Being able to select the text and copy it would I guess be useful in case I ever wanted to use it for documentation. – Mr. Boy Dec 03 '15 at 11:06