3

我正在处理一个包含大量项目的大型代码库,每个项目都有少数(在某些情况下,大量)对其他项目的引用。随着时间的推移,对这个代码库进行了大量的重构,结果有许多程序集被一些项目引用,只是因为它们曾经包含一个已经转移到其他地方的类;之类的东西。

ReSharper 有一个集成到 IDE 中的工具,允许用户为给定项目找到实际使用给定引用的代码,但是为了将其转变为解决方案,我们需要让一个人右键单击每个项目中的每个引用然后实际检查没有使用然后删除它们,这不仅是一个漫长的过程,而且接近于折磨。

我希望能够自动化这个过程,以便我们只运行它并删除不必要的引用;然后,我们或许可以将其整合到某种常规流程中,以便发现被忽略的错误。

我想到的两个选项是 A) 如果可能的话,使用 Powershell 自动化 ReSharper,或者 B) 也许 Visual Studio 2010 架构依赖关系图可以处理这个问题,如果幸运的话,也许可以以可编写脚本的方式处理。

我的问题是:

  • 可以为 ReSharper 编写这样的脚本吗?
  • VS2010 架构是否提供以任何批处理/自动方式删除未使用的引用?
4

3 回答 3

6

你应该可以用简单的powershell来做到这一点:

1)用你的解决方案加载视觉工作室

2)编译整个解决方案

3)让VS运行并启动powershell.exe

4) 从 ROT 中获取对仍在运行的 VS 的 DTE 实例的引用(重要 - 确保只有一个实例在运行 - 如果它被提升,powershell 也应该是):

ps> $dte = [System.Runtime.InteropServices.Marshal]::GetActiveObject("visualstudio.dte")

5)通过枚举解决方案中的所有项目及其引用进行测试:

ps> $dte.solution.projects | select @{l="name";e={$_.name}}, `
        @{l="references";e={$_.object.references|select -exp name}} | ft -auto

...转储所有项目名称和引用...

6) 现在,编写一些脚本来遍历解决方案文件夹和项目

7) 当您点击 bin\ 文件夹时,加载仅反射加载的程序集:

$assembly = [reflection.assembly]::reflectiononlyload($dll)

8) 在输出程序集中获取实际引用的程序集

$refs = $assembly.getreferencedassemblies()

9)将实际引用的程序集与项目中引用的程序集进行比较,并通过VS DTE对象模型删除多余的程序集

# example
$currentproj.object.references.item("system.core").remove()
$currentproj.save()

10) 利润!

这是有效的,因为 .net 仅链接代码中实际引用的程序集。抱歉,我无法发布完整的工作示例,但这应该足以让您入门。

-Oisin

于 2011-01-29T05:41:37.040 回答
1

不是一个完整的解决方案,但请查看Resolve csproj dependencies when projects are depended from bin as well and How to find wrong assembly dependencies through PowerShell。有一种方法可以找到对其他项目的引用以及如何在程序集中找到引用。

第二部分与 Oisin 提出的相同。第一个略有不同 - 它从 csproj 文件中获取引用(作为 xml 文件并以这种方式处理)。

至少把它当作一种灵感;)

于 2011-01-29T20:45:20.463 回答
1

我按照@x0n 的指示进行操作,但对我来说效果不佳。也许我错过了什么。我不得不承认,由于 COM 错误,我无法加载我dll的 s 。ReflectionOnlyLoad所以我用LoadFile. 当我使用 Reflector 加载程序集时,提供的程序集引用LoadFile完全相同。最后,我的 PowerShell 脚本生成了一个列表,其中显示了项目中但程序集未加载的引用。从理论上讲,这些应该是“不必要的”引用。当我开始删除它们时,构建失败了。例如,在我的第一个项目中,缺少 4 个“不必要的”引用中的任何一个都会导致构建失败。我浏览了 powershell 脚本的输出,它列出了“System" 例如。如果我删除它,编译器甚至不会抱怨一堆 " using System;" 但在此之前它会失败 - 说明我需要因为接口而引用该程序集......顺便说一句,我们的项目不是玩具,它涉及 140 多个 dll(nUnit尽管其中几乎一半是测试 dll),我想我会做一些家务。我的脚本(它不会递归进入项目文件夹 - 一些项目包含更多 dll)所以也许有人可以用它:

`
$dte = [System.Runtime.InteropServices.Marshal]::GetActiveObject("visualstudio.dte")

$binfiles=Get-ChildItem C:\YourSourcePath\bin\debug
$dlls=$binfiles | where { $_.extension -eq ".dll" -and $_.name -like "*YourCompanyName*" }

foreach ($dll in $dlls) {
    foreach($prj in $dte.solution.projects) {
        if ($prj.Kind -eq "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") {
            if ($prj.Properties.Item("OutputFileName").Value -eq $dll.Name) {
                $loaded = [reflection.assembly]::LoadFile($dll.FullName)
                $refs = $loaded.GetReferencedAssemblies()
                Write "============="
                Write $dll.Name
                Write "-------------"
                foreach($pref in $prj.Object.References) {
                    $found = 0
                    foreach($ref in $refs) {
                        if ($ref.Name -eq $pref.Name) {
                            $found = 1
                            break;
                        }
                    }
                    if ($found -eq 0) {
                        Write $pref.Name
                    }
                }
            }
        }
    }
}

`

于 2012-12-05T00:49:12.197 回答