【问题标题】:Find Unused Resources in a .NET Solution在 .NET 解决方案中查找未使用的资源
【发布时间】:2021-03-02 01:21:35
【问题描述】:

如何在 .resx 文件中查找可能已“孤立”且不再需要的未使用图标、图像、字符串?

【问题讨论】:

    标签: .net resources


    【解决方案1】:

    最近ResXManager 1.0.0.41添加了一个功能来显示对字符串资源的引用次数。

    【讨论】:

    • 这个工具太棒了!
    • 当然。多么救命啊。它不仅向您显示列中的使用次数,还允许您按使用次数排序。然后您可以阻止选择所有“0”用法并一键删除。通过这种方式,我设法在几秒钟内从解决方案中删除了 300 多个未使用的字符串。我只是给他们捐了钱。我可能会再来一次。太棒了!
    • 任何想法,为什么这个工具找不到所有参考?它是否要求代码文件位于特定文件夹或其他东西中?似乎正在搜索 App_Code 文件夹,而不是其他文件夹。我们在根目录中有一些 .aspx 文件,在其他文件夹中有一些用户控件。
    • 我已经使用 ResXManager 很长时间了,但是从来没有注意到这个功能!太好了!
    【解决方案2】:

    我找不到任何可以在 XAML 文件中搜索字符串资源引用并批量删除未使用的资源引用的现有解决方案。

    所以我写了这个:https://github.com/Microsoft/RESX-Unused-Finder

    它在项目目录中搜索对字符串资源的引用,然后显示找不到匹配项的列表。您可以指定要搜索的模板,以便它可以在 XAML 文件中找到引用。

    【讨论】:

    • +1。如果可能的话会给予更多。一段时间以来一直在寻找一个很棒的工具,这个工具对我来说很突出!干得好!
    • 这个工具非常棒,尤其是在您使用 WPF 时。我们生成代理 AppResources 的类,这个工具可以完美地处理它。我们使用自定义 XAML 标记扩展,它也适用于此。做得很好。
    • 几个问题 - 不构建,但添加对 System.Windows.Interactivity 的引用。取消选中签署 ClickOnce 清单,取消选中启用 ClickOnce 安全性。之后,解决方案构建。
    • @AH。谢谢。我删除了签名(使用过期的临时证书)并更新了 ClickOnce 托管位置。我认为它会遇到一些智能屏幕警告,但希望它们会随着它被更频繁地使用而消失。
    • 否则很棒的应用程序。谢谢。
    【解决方案3】:

    我创建了一个免费的开源 VS 扩展,用于查找项目中未使用的图像,刚刚发布了第一个版本:https://marketplace.visualstudio.com/items?itemName=Jitbit1.VSUnusedImagesFinder

    【讨论】:

    • 这对我来说没有按预期工作。它删除了使用过的图片
    • @Jack 请在 Github 页面上报告问题,描述图像是如何“使用”的,以便我们修复它
    【解决方案4】:

    这不是算法可以可靠计算的信息。被检查的程序可以获取所有资源的列表并对它们做一些事情,比如让用户从几个图标中进行选择。

    您最好的选择可能是搜索对您选择的资源访问 API 的所有引用并手动检查这些引用。使用grep/sed,您可以通过处理所有使用简单字符串的“简单”站点来减少必须手动检查的站点。

    【讨论】:

    • 这从来都不是真的,因为自动生成的 Designer 文件是一个类,您可以根据其方法验证引用以找到您需要的内容。如果你使用的是新的 Visual Studio,那么如果你有 CodeLens 会更容易。
    • @RodneyS.Foley "never true" 是一种强有力的语言,特别是考虑到当且仅当应用程序仅使用自动生成的设计器时,您跟进的东西是真实的,这只是一小部分在应用中如何使用资源的可能性。
    • “这不是算法可以可靠计算的信息。”不是一个真实的陈述。有免费的扩展,特别是一个,它使用一种可靠地计算这一点的算法。 Visual Studio 可以并且确实计算了这个,Resharper 可以并且确实计算了这个。
    【解决方案5】:

    由于我还找不到简单快速解决方案,我至少找到了一个解决方案,可以让我得到我正在寻找的结果,即使这需要一些时间(非常适合慵懒的周日下午)。

    解决方案涉及 Visual Studio .NET 2010 和 ReSharper(我使用的是 7.1 版),如下所示。

    分步解决方案

    1.) 右键单击​​ VS.NET 中的主 RESX 文件,然后从上下文菜单中选择“查找用法”:

    这将打开 ReSharper 的“查找结果”窗口。

    2.)双击解决方案窗口中的每个匹配项:

    这将打开包含资源的源代码窗口。

    3.) 在源代码窗口中重命名此资源:

    它将调出 ReSharper 的“重命名资源”对话框。

    4.) 为资源指定一个带有唯一前缀的新名称。在我的示例中,这是“TaskDialog_”:

    它将重命名资源以及自动生成的 C# 包装器/访问类。

    5.) 对“使用”窗口中的所有资源重复上述步骤 2、3 和 4。

    6.) 在 Visual Studio 的资源编辑器中打开 RESX 文件并选择所有不带前缀的文件:

    7.) 现在单击窗口顶部的“删除资源”按钮,或者只需按 Del 键:

    您终于有了一个 RESX 文件,其中只有文件中实际使用的资源。

    8.)(可选)如果您有多种语言的资源(例如德语的“Resources.de.resx”),也对这些 RESX 文件重复步骤 7 和 8。 p>

    警告

    请注意,如果您通过强类型、自动生成的 C# 类 Resources 以外的方式访问字符串,这将不起作用。

    【讨论】:

      【解决方案6】:

      我最近构建了一个工具来检测和删除未使用的字符串资源。我使用这篇文章中的信息作为参考。该工具可能并不完美,但它完成了繁重的工作,如果您有一个历史悠久的大型项目,它将很有用。我们在内部使用此工具来整合资源文件,并删除未使用的资源(我们从 10,000 个资源中删除了 4,000 多个资源)。

      您可以查看源代码,或者直接从这里安装 ClickOnce:https://resxutils.codeplex.com/

      【讨论】:

      • 这看起来很有希望(一旦我发现你必须删除 Resources.Designer.cs 才能让它显示任何结果)。但它无法在 XAML 文件中找到引用,这是一个大问题。
      【解决方案7】:

      我遇到了类似的问题。我为翻译表创建了数千个资源字符串,其中许多不再需要或通过代码引用。由于有大约 180 个依赖代码文件,我无法手动遍历每个资源字符串。

      以下代码(在 vb.net 中)将通过您的项目查找孤立资源(在 项目资源 中,而不是任何单个表单的资源)。我的项目花了大约 1 分钟。可以修改它以查找字符串、图像或任何其他资源类型。

      总结一下;

      • 1) 使用解决方案项目文件收集所有包含的代码 模块并将它们附加到单个字符串变量中;
      • 2) 循环遍历所有项目资源对象,并创建一个字符串列表(在我的例子中);
      • 3) 是否在组合项目文本变量中进行字符串搜索以查找资源字符串代码;
      • 4) 报告未引用的资源对象。

      该函数返回 Windows 剪贴板上的对象名称,以便粘贴到电子表格中或作为资源名称的列表数组。

      edit:模块中的示例调用:modTest
      ? modTest.GetUnusedResources("C:\Documents and Settings\me\My Documents\Visual Studio 2010\Projects\myProj\myProj.vbproj", True, true)

      'project file is the vbproj file for my solution
      Public Function GetUnusedResources(projectFile As String, useClipboard As Boolean, strict As Boolean) As List(Of String)
      
      
          Dim myProjectFiles As New List(Of String)
          Dim baseFolder = System.IO.Path.GetDirectoryName(projectFile) + "\"
      
          'get list of project files 
          Dim reader As Xml.XmlTextReader = New Xml.XmlTextReader(projectFile)
          Do While (reader.Read())
              Select Case reader.NodeType
                  Case Xml.XmlNodeType.Element 'Display beginning of element.
                      If reader.Name.ToLowerInvariant() = "compile" Then ' only get compile included files
                          If reader.HasAttributes Then 'If attributes exist
                              While reader.MoveToNextAttribute()
                                  If reader.Name.ToLowerInvariant() = "include" Then myProjectFiles.Add((reader.Value))
                              End While
                          End If
                      End If
              End Select
          Loop
      
          'now collect files into a single string
          Dim fileText As New System.Text.StringBuilder
          For Each fileItem As String In myProjectFiles
              Dim textFileStream As System.IO.TextReader
              textFileStream = System.IO.File.OpenText(baseFolder + fileItem)
              fileText.Append(textFileStream.ReadToEnd)
              textFileStream.Close()
          Next
          '  Debug.WriteLine(fileText)
      
          ' Create a ResXResourceReader for the file items.resx.
          Dim rsxr As New System.Resources.ResXResourceReader(baseFolder + "My Project\Resources.resx")
          rsxr.BasePath = baseFolder + "Resources"
          Dim resourceList As New List(Of String)
          ' Iterate through the resources and display the contents to the console.
          For Each resourceValue As DictionaryEntry In rsxr
              ' Debug.WriteLine(resourceValue.Key.ToString())
              If TypeOf resourceValue.Value Is String Then ' or bitmap or other type if required
                  resourceList.Add(resourceValue.Key.ToString())
              End If
          Next
          rsxr.Close()  'Close the reader.
      
          'finally search file string for occurances of each resource string
          Dim unusedResources As New List(Of String)
          Dim clipBoardText As New System.Text.StringBuilder
          Dim searchText = fileText.ToString()
          For Each resourceString As String In resourceList
              Dim resourceCall = "My.Resources." + resourceString ' find code reference to the resource name
              Dim resourceAttribute = "(""" + resourceString + """)" ' find attribute reference to the resource name
              Dim searchResult As Boolean = False
              searchResult = searchResult Or searchText.Contains(resourceCall)
              searchResult = searchResult Or searchText.Contains(resourceAttribute)
              If Not strict Then searchResult = searchResult Or searchText.Contains(resourceString)
              If Not searchResult Then ' resource name no found so add to list
                  unusedResources.Add(resourceString)
                  clipBoardText.Append(resourceString + vbCrLf)
              End If
          Next
      
          'make clipboard object
          If useClipboard Then
              Dim dataObject As New DataObject ' Make a DataObject clipboard
              dataObject.SetData(DataFormats.Text, clipBoardText.ToString())        ' Add the data in string format.
              Clipboard.SetDataObject(dataObject) ' Copy data to the clipboard.
          End If
      
          Return unusedResources
      
      End Function
      

      【讨论】:

      • 谢谢,希望您不介意我添加一两个额外的注释。我们有一个包含几千个资源字符串的表单,我们需要对其进行调查,所以这在整个过程中很有用。事实证明,该表单具有其 Localizable 属性 True,因此所有控件的设置都存储在表单的 resx 中。设置为 false 将事情恢复正常并将 resz 大小从 600+k 缩小到 35k!
      【解决方案8】:

      我使用 ReSharper 来查找未使用的资源字段,然后如果项目包含少量资源,则手动删除它们。如果我们已经有未使用项目的列表,可以使用一些简短的脚本。

      接下来是解决办法:

      • 显示所有未使用的成员,如this article 中所述
      • 从生成的文件掩码中临时删除 *.Designer.cs (ReSharper → 选项 → CodeInspection → GeneratedCode)
      • 还注释或删除注释(表示代码是自动的 生成)从附加到资源文件的 Designer.cs 文件顶部。

      您将获得所有未使用资源的列表,以便将它们从 resx 中删除。

      【讨论】:

        【解决方案9】:

        我自己一直在考虑这个问题,我相信我有两个选择。这两者都依赖于我使用辅助方法从资源文件中提取所需资源的事实。

        1. 日志记录
          将一些代码添加到“getresource”方法或方法中,以便每次访问资源时,将资源键写入日志。然后尝试访问站点的每个部分(测试脚本在这里可能会有所帮助)。生成的日志条目应提供所有活动资源键的列表,其余的可以被垃圾。

        2. 代码分析
          我正在查看T4 是否能够完成解决方案并创建对“getresource”辅助方法的所有引用的列表。生成的键列表将处于活动状态,其余的可以删除。

        这两种方法都有局限性。日志记录方法仅与测试涵盖的代码一样好,并且代码分析可能并不总是找到键而不是包含键的字符串,因此那里需要一些额外的手动工作。

        我想我会尝试两者。我会告诉你进展如何。

        【讨论】:

          【解决方案10】:

          重命名您当前的图像目录,然后创建一个新目录,在 VS 中进行文件查找搜索您的图像路径,即“/content/images”,多选所有使用的图像并将它们拖到新图像中文件夹。 然后,您可以从项目中排除旧目录,或者直接删除它。

          【讨论】:

          • 问题不在于目录中的物理图像,而在于 resx 文件中的资源。
          猜你喜欢
          • 1970-01-01
          • 2011-02-04
          • 2019-04-24
          • 2013-12-25
          • 2015-03-10
          • 2015-02-14
          • 2019-03-24
          • 2018-12-15
          • 2019-12-26
          相关资源
          最近更新 更多