在 .NET 解决方案中查找未使用的资源
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/245956/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find Unused Resources in a .NET Solution
提问by gleng
How do you go about finding unused icons, images, strings in .resx files that may have become 'orphaned' and are no longer required?
您如何在 .resx 文件中查找未使用的图标、图像、字符串,这些文件可能已成为“孤立的”并且不再需要?
采纳答案by David Schmitt
This is no information an algorithm can reliably compute. The inspected program could fetch a list of all resources and do something with them, like letting the user choose from several icons.
这不是算法可以可靠计算的信息。被检查的程序可以获取所有资源的列表并用它们做一些事情,比如让用户从几个图标中进行选择。
Your best bet is probably to search for all references to your resource-access API of choice and inspect those manually. Using grep/sedyou might be able to reduce the sites you have to inspect manually by handling all "easy" ones where a simple string is used.
您最好的办法可能是搜索对您选择的资源访问 API 的所有引用并手动检查这些引用。使用grep/sed您可以通过处理所有使用简单字符串的“简单”站点来减少必须手动检查的站点。
回答by hultqvist
Recently ResXManager 1.0.0.41added a feature to show the number of references to a string resource.
最近ResXManager 1.0.0.41添加了一个功能来显示对字符串资源的引用次数。


回答by RandomEngy
I couldn't find any existing solution that would search for string resource references in XAML files and batch-remove unused ones.
我找不到任何可以在 XAML 文件中搜索字符串资源引用并批量删除未使用的资源引用的现有解决方案。
So I wrote this: https://github.com/Microsoft/RESX-Unused-Finder
所以我写了这个:https: //github.com/Microsoft/RESX-Unused-Finder
It searches a project directory for references to string resources, then displays a list of ones it couldn't find a match for. You can specify a template to search for so it can find references in XAML files.
它在项目目录中搜索对字符串资源的引用,然后显示找不到匹配项的列表。您可以指定要搜索的模板,以便它可以在 XAML 文件中找到引用。
回答by Alex
I created a free open-source VS extension that looks for unused images in a project, just published the first version: https://marketplace.visualstudio.com/items?itemName=Jitbit1.VSUnusedImagesFinder
我创建了一个免费的开源 VS 扩展,用于查找项目中未使用的图像,刚刚发布了第一个版本:https: //marketplace.visualstudio.com/items?itemName=Jitbit1.VSUnusedImagesFinder
回答by Uwe Keim
Since I could not find a simpleand fastsolution yet, I found at least a solution that allows me to get the result I'm looking for, even if it takes some time (ideal for a lazy sunday afternoon).
因为我无法找到一个简单和快速的解决方案然而,我发现至少有一个解决方案,可以让我获得我正在寻找的结果,即使这需要一定的时间(适用于慵懒的周日下午)。
The solution involves Visual Studio .NET 2010 and ReSharper (I'm using version 7.1) and goes like the following.
该解决方案涉及 Visual Studio .NET 2010 和 ReSharper(我使用的是 7.1 版),如下所示。
Step-by-step solution
分步解决方案
1.)Right-click your primary RESX file in VS.NET and select "Find Usages" from the context menu:
1.)在 VS.NET 中右键单击您的主要 RESX 文件,然后从上下文菜单中选择“Find Usages”:


This will bring up ReSharper's "Find Results" window.
这将打开 ReSharper 的“查找结果”窗口。
2.)Double-click each occurrence in the solution window:
2.)双击解决方案窗口中的每个事件:


This will open the source code window with the resource.
这将打开包含资源的源代码窗口。
3.)Rename this resource from within the source code window:
3.)从源代码窗口中重命名此资源:


It will bring up ReSharper's "Rename Resource" dialog.
它将打开 ReSharper 的“重命名资源”对话框。
4.)Give the resource a new name with a unique prefix. In my example this is "TaskDialog_":
4.)给资源一个唯一前缀的新名称。在我的示例中,这是“TaskDialog_”:


It will rename both the resource and also the auto-generated C# wrapper/access class.
它将重命名资源和自动生成的 C# 包装器/访问类。
5.)Repeat the above steps 2, 3 and 4 for all resources in the "Usages" window.
5.)对“使用”窗口中的所有资源重复上述步骤 2、3 和 4。
6.)Open the RESX file in Visual Studio's resource editor and select all files without the prefix:
6.)在 Visual Studio 的资源编辑器中打开 RESX 文件并选择所有没有前缀的文件:


7.)Now click the "Remove Resource" button on the top of the window or simply press the Delkey:
7.)现在单击窗口顶部的“删除资源”按钮或只需按以下Del键:


You finally have a RESX file with only the acutally used resources in your file.
您最终拥有一个仅包含文件中实际使用的资源的 RESX 文件。
8.)(Optionally) If you have resources in multiple languages (e.g. "Resources.de.resx" for German), repeat steps 7 and 8 for those RESX files, too.
8.)(可选)如果您有多种语言的资源(例如德语的“Resources.de.resx”),也对这些 RESX 文件重复步骤 7 和 8。
Warning
警告
Please note that this will not work if you access your strings other than through the strongly-typed, auto-generated C# class Resources.
请注意,如果您不是通过强类型、自动生成的 C# 类访问您的字符串,这将不起作用Resources。
回答by votrubac
I recently built a tool that detects and removes unused string resources. I used the information in this post as a reference. The tool may not be perfect, but it does the heavy-lifting part and will be useful if you have a big project with the long history. We used this tool internally to consolidate resource files, and remove unused resources (we got rid of 4,000+ resources out of 10,000).
我最近构建了一个工具来检测和删除未使用的字符串资源。我使用了这篇文章中的信息作为参考。该工具可能并不完美,但它可以完成繁重的工作,如果您有一个历史悠久的大型项目,它将非常有用。我们在内部使用这个工具来整合资源文件,并删除未使用的资源(我们摆脱了 10,000 个资源中的 4,000+ 个)。
You can look at the source code, or just install ClickOnce from here: https://resxutils.codeplex.com/
您可以查看源代码,或者直接从这里安装 ClickOnce:https: //resxutils.codeplex.com/
回答by Anatoliy
I use ReSharper for finding unused resource fields and then remove them manually if project contains small amount of resources. Some short script can be used if we already have list of unused items.
我使用 ReSharper 查找未使用的资源字段,然后如果项目包含少量资源,则手动删除它们。如果我们已经有未使用项目的列表,则可以使用一些简短的脚本。
The solution is next:
解决方法如下:
- show all unused members as described in this article
- temporary remove *.Designer.cs from Generated file masks (ReSharper → Options → CodeInspection → GeneratedCode)
- Also comment or remove comment (that indicates that code is auto generated) from top of Designer.cs file attached to resource file.
- 显示本文中描述的所有未使用的成员
- 从生成的文件掩码中临时删除 *.Designer.cs(ReSharper → 选项 → CodeInspection → GeneratedCode)
- 还可以从附加到资源文件的 Designer.cs 文件顶部注释或删除注释(表示代码是自动生成的)。
You will have list of all unused resources, left to remove them from resx.
您将拥有所有未使用资源的列表,以便从 resx 中删除它们。
回答by Craig Stewart
I had a similar problem. Several thousand resource strings that I'd created for a translation table, many of which were no longer required or reference by code. With around 180 dependent code files, there was no way I was going to manually go through each resource string.
我有一个类似的问题。我为转换表创建的数千个资源字符串,其中许多不再需要或不再被代码引用。有大约 180 个依赖代码文件,我无法手动检查每个资源字符串。
The following code (in vb.net) will go through your project finding orphaned resources (in the project resources, not any individual forms' resources). It took around 1 minute for my project. It can be modified to find strings, images or any other resource type.
以下代码(在 vb.net 中)将通过您的项目查找孤立资源(在项目资源中,而不是任何单个表单的资源中)。我的项目花了大约 1 分钟。可以修改它以查找字符串、图像或任何其他资源类型。
In summary it;
总结一下吧;
- 1) Uses the solution project file to gather all the included code modules and appends them into a single string variable;
- 2) Loops through all the project resource objects, and creates a list (in my case) of those which are strings;
- 3) Does a string search finding resource string codes in the combined project text variable;
- 4) Reports resource objects that are not referenced.
- 1) 使用解决方案项目文件收集所有包含的代码模块并将它们附加到单个字符串变量中;
- 2)循环遍历所有项目资源对象,并创建一个列表(在我的例子中)是字符串;
- 3) 进行字符串搜索,在组合项目文本变量中查找资源字符串代码;
- 4) 报告未被引用的资源对象。
The function returns the object names on the windows clipboard for pasting in a spreadsheet or as a list array of the resource names.
该函数返回 Windows 剪贴板上的对象名称,以便粘贴到电子表格中或作为资源名称的列表数组。
edit: example call in module : modTest? modTest.GetUnusedResources("C:\Documents and Settings\me\My Documents\Visual Studio 2010\Projects\myProj\myProj.vbproj", True, true)
编辑:模块中的示例调用: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
回答by Chris Simpson
I've been considering this myself and I believe I have two options. Both of these rely on the fact that I use a helper method to extract the required resource from the resource files.
我自己一直在考虑这个问题,我相信我有两个选择。这两者都依赖于我使用辅助方法从资源文件中提取所需资源的事实。
Logging
Add some code to the "getresource" method or methods so that every time a resource is accessed, the resource key is written to a log. Then try to access every part of the site (a testing script might be helpful here). The resultant log entries should give a list of all the active resource keys, the rest can be junked.Code Analysis
I am looking at whether T4is capable of working through the solution and creating a list of all references to the "getresource" helper method. The resultant list of keys will be active, the rest can be deleted.
日志记录
在“getresource”方法或方法中添加一些代码,以便每次访问资源时,将资源密钥写入日志。然后尝试访问站点的每个部分(测试脚本在这里可能会有所帮助)。结果日志条目应该给出所有活动资源键的列表,其余的可以被丢弃。代码分析
我正在研究T4是否能够完成解决方案并创建对“getresource”帮助程序方法的所有引用的列表。生成的密钥列表将处于活动状态,其余的可以删除。
There are limitations of both methods. The logging method is only as good as the code covered by the test and the code analysis might not always find keys rather than strings containg the keys so there will be some extra manual work required there.
这两种方法都有局限性。日志记录方法仅与测试覆盖的代码一样好,并且代码分析可能并不总是找到键而不是包含键的字符串,因此需要一些额外的手动工作。
I think I'll try both. I'll let you know how it goes.
我想我会尝试两个。我会让你知道它是怎么回事。
回答by DevHead
Rename your current image directory and then create a new one, do a find-in-files search within VS for your image path, i.e. '/content/images', multiselect all the used images and drag them into the new image folder. You can then exclude the old directory from the project, or just delete it.
重命名当前图像目录,然后创建一个新目录,在 VS 中进行文件查找以查找图像路径,即“/content/images”,多选所有使用过的图像并将它们拖到新的图像文件夹中。然后,您可以从项目中排除旧目录,或者直接将其删除。

