查找SDK风格项目的依赖

Find dependencies of SDK-style projects

在 Visual Studio 扩展中,我需要遍历加载的解决方案中的所有项目并找到所有依赖项(NuGet 包和程序集)。以下代码适用于旧的非 SDK 样式项目,但不适用于新的 SDK 样式项目。

var dte = ApplicationObject; // DTE object
if (dte == null || dte.Solution == null || !dte.Solution.IsOpen)
{
    return;
}

foreach (Project project in dte.Solution.Projects)
{
    var vsProj = project.Object as VSProject;
    if (vsProj == null || vsProj.References == null)
    {
        // Project not loaded
        continue;
    }

    foreach (Reference reference in vsProj.References)
    {
        if (reference.SourceProject != null 
            || reference.Type != prjReferenceType.prjReferenceTypeAssembly)
        {
            // Skip over non assembly references
            continue;
        }

        // reference.Name contains the reference name
    }
}

在新的 SDK 样式项目中,"references" 现在称为依赖项,但 VSProject 上没有这样的 属性。那么SDK风格的项目怎么获取呢?

So what is the way to get this for SDK-style projects?

恐怕答案是否定的。这可能是一个与VS2019 SDK和新SDK项目系统相关的问题。

并且此问题专门发生在 IVsSolutionEvents.OnAfterOpenSolution 事件中。我试图在 OnQueryCloseSolution 事件或 Command Item 的点击事件中调用类似的代码,但对于其中包含 one .net core 应用程序的相同解决方案,它都运行良好。

我认为这可能是一个问题,因为解决方案和项目不为空(我输出 xx.sln 和 xx.csproj),但它无法从 reference.Name vsProj.References。它在关闭解决方案时有效,但现在打开 solution.For 时得到空列表,我发现没有有效的解决方法使其有效。

问题已报告给DC,如果有人对此感兴趣,可以跟踪问题here

VS2019工程是.net core 3.1库工程,打开解决方案后如下代码。实际上是检索存储在 nuget 位置中的引用的路径位置:

C:\Users\xxxxx\.nuget\packages\subsonic.core.dal.2.1\lib\netstandard2.1\SubSonic.Core.DataAccessLayer.dll

public string ResolveAssemblyReference(string assemblyReference)
{
    ThreadHelper.ThrowIfNotOnUIThread();

    string path = EngineHost.ResolveAssemblyReference(assemblyReference);

    if (path.Equals(assemblyReference, StringComparison.Ordinal) &&
        !foundAssembly.IsMatch(path))
    {   // failed to find the assembly, could it be referenced via a project reference?
        if (GetService(typeof(DTE)) is DTE dTE)
        {
            foreach (Project project in dTE.Solution.Projects)
            {
                if (project.Object is VSProject vsProject)
                {
                    path = ResolveAssemblyReferenceByProject(assemblyReference, vsProject.References);
                }
                else if (project.Object is VsWebSite.VSWebSite vsWebSite)
                {
                    path = ResolveAssemblyReferenceByProject(assemblyReference, vsWebSite.References);
                }
            }
        }

        if (!foundAssembly.IsMatch(path))
        {
            LogError(false, SubSonicCoreErrors.FileNotFound, -1, -1, $"{assemblyReference}.dll");
        }
    }

    return path;
}

private string ResolveAssemblyReferenceByProject(string assemblyReference, References references)
{
    foreach (Reference reference in references)
    {
        if (reference.Name.Equals(assemblyReference, StringComparison.OrdinalIgnoreCase))
        {   // found the reference
            return reference.Path;
        }
    }

    return assemblyReference;
}

private string ResolveAssemblyReferenceByProject(string assemblyReference, VsWebSite.AssemblyReferences references)
{
    foreach (VsWebSite.AssemblyReference reference in references)
    {
        if (reference.Name.Equals(assemblyReference, StringComparison.OrdinalIgnoreCase))
        {   // found the reference
            return reference.FullPath;
        }
    }

    return assemblyReference;
}