IT story

.NET 솔루션에서 사용하지 않는 리소스 찾기

hot-time 2021. 1. 7. 20:02
반응형

.NET 솔루션에서 사용하지 않는 리소스 찾기


'분리'되어 더 이상 필요하지 않은 .resx 파일에서 사용하지 않는 아이콘, 이미지, 문자열을 찾는 방법은 무엇입니까?


이것은 알고리즘이 안정적으로 계산할 수있는 정보가 아닙니다. 검사 된 프로그램은 모든 리소스 목록을 가져 와서 사용자가 여러 아이콘 중에서 선택하도록하는 것과 같은 작업을 수행 할 수 있습니다.

가장 좋은 방법은 선택한 리소스 액세스 API에 대한 모든 참조를 검색하고 수동으로 검사하는 것입니다. grep/ sed사용 하면 간단한 문자열이 사용되는 "쉬운"사이트를 모두 처리하여 수동으로 검사해야하는 사이트를 줄일 수 있습니다.


최근 ResXManager 1.0.0.41 은 문자열 리소스에 대한 참조 수를 표시하는 기능을 추가했습니다.

새로운 참조 열을 보여주는 스크린 샷


XAML 파일에서 문자열 리소스 참조를 검색하고 사용하지 않는 항목을 일괄 제거하는 기존 솔루션을 찾을 수 없습니다.

그래서 저는 이것을 썼습니다 : https://github.com/Microsoft/RESX-Unused-Finder

RESX 미사용 파인더 스크린 샷

프로젝트 디렉터리에서 문자열 리소스에 대한 참조를 검색 한 다음 일치 항목을 찾을 수없는 목록을 표시합니다. XAML 파일에서 참조를 찾을 수 있도록 검색 할 템플릿을 지정할 수 있습니다.


프로젝트에서 사용하지 않는 이미지를 찾는 무료 오픈 소스 VS 확장을 만들었고 방금 첫 번째 버전을 게시했습니다 : https://marketplace.visualstudio.com/items?itemName=Jitbit1.VSUnusedImagesFinder


아직 간단 하고 빠른 솔루션을 찾을 수 없었기 때문에 , 시간이 좀 걸리더라도 (게으른 일요일 오후에 이상적) 원하는 결과를 얻을 수있는 솔루션을 적어도 찾았습니다.

솔루션에는 Visual Studio .NET 2010 및 ReSharper (버전 7.1을 사용하고 있음)가 포함되며 다음과 같습니다.

단계별 솔루션

1.) VS.NET에서 기본 RESX 파일을 마우스 오른쪽 단추로 클릭하고 상황에 맞는 메뉴에서 "사용 찾기"를 선택합니다.

여기에 이미지 설명 입력

ReSharper의 "결과 찾기"창이 나타납니다.

2.) 솔루션 창에서 각 항목을 두 번 클릭합니다.

여기에 이미지 설명 입력

그러면 리소스가있는 소스 코드 창이 열립니다.

3.) 소스 코드 창에서이 리소스의 이름을 바꿉니다.

여기에 이미지 설명 입력

ReSharper의 "Rename Resource"대화 상자가 나타납니다.

4.) 리소스에 고유 한 접두사가 있는 새 이름을 지정 합니다 . 내 예에서는 "TaskDialog_"입니다.

여기에 이미지 설명 입력

리소스와 자동 생성 된 C # 래퍼 / 액세스 클래스의 이름을 모두 바꿉니다.

5.) "사용"창의 모든 리소스에 대해 위의 2, 3 및 4 단계를 반복합니다.

6.) Visual Studio의 리소스 편집기에서 RESX 파일을 열고 접두사가없는 모든 파일을 선택합니다.

여기에 이미지 설명 입력

7.) 이제 창 상단의 "리소스 제거"버튼을 클릭하거나 간단히 Del를 누르십시오 .

여기에 이미지 설명 입력

마지막으로 파일에 사용 된 리소스 만 포함 된 RESX 파일이 생겼습니다.

8.) (선택 사항) 여러 언어로 된 리소스 (예 : 독일어의 경우 "Resources.de.resx")가있는 경우 해당 RESX 파일에 대해서도 7 단계와 8 단계를 반복합니다.

경고

강력한 형식의 자동 생성 C # 클래스를 통하지 않고 다른 문자열에 액세스하는 경우에는 작동하지 않습니다 Resources.


최근에 사용하지 않는 문자열 리소스를 감지하고 제거하는 도구를 만들었습니다. 이 게시물의 정보를 참고 자료로 사용했습니다. 이 도구는 완벽하지 않을 수 있지만 무거운 작업을 수행하며 오랜 역사를 가진 큰 프로젝트가있는 경우 유용 할 것입니다. 이 도구를 내부적으로 사용하여 리소스 파일을 통합하고 사용하지 않는 리소스를 제거했습니다 (10,000 개 중 4,000 개 이상의 리소스 제거).

소스 코드를 보거나 여기에서 ClickOnce를 설치할 수 있습니다. https://resxutils.codeplex.com/


비슷한 문제가있었습니다. 번역 테이블을 위해 만든 수천 개의 리소스 문자열 중 많은 부분이 더 이상 코드에서 필요하지 않거나 참조되지 않았습니다. 약 180 개의 종속 코드 파일이 있으므로 각 리소스 문자열을 수동으로 살펴볼 방법이 없었습니다.

다음 코드 (vb.net)는 고아 리소스 ( 개별 양식의 리소스가 아닌 프로젝트 리소스 에서)를 찾는 프로젝트를 살펴 봅니다. 내 프로젝트에는 약 1 분이 걸렸습니다. 문자열, 이미지 또는 기타 리소스 유형을 찾도록 수정할 수 있습니다.

요약하면,

  • 1) 솔루션 프로젝트 파일을 사용하여 포함 된 모든 코드 모듈을 수집하고 단일 문자열 변수에 추가합니다.
  • 2) 모든 프로젝트 리소스 개체를 반복하고 문자열 인 목록 (제 경우에는)을 만듭니다.
  • 3) Does a string search finding resource string codes in the combined project text variable;
  • 4) Reports resource objects that are not referenced.

The function returns the object names on the windows clipboard for pasting in a spreadsheet or as a list array of the resource names.

edit : example call in module : 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

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.

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.

You will have list of all unused resources, left to remove them from resx.


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.

  1. 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.

  2. Code Analysis
    I am looking at whether T4 is 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.

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.


현재 이미지 디렉토리의 이름을 바꾼 다음 새 디렉토리를 만들고 VS 내에서 이미지 경로 (예 : '/ content / images')를 검색하고 사용 된 모든 이미지를 다중 선택하여 새 이미지 폴더로 드래그합니다. 그런 다음 프로젝트에서 이전 디렉토리를 제외하거나 삭제할 수 있습니다.

참조 URL : https://stackoverflow.com/questions/245956/find-unused-resources-in-a-net-solution

반응형