Trova risorse inutilizzate in una soluzione .NET
Domanda
Come si fa a trovare icone, immagini, stringhe inutilizzate nei file .resx che potrebbero essere diventati "orfani" e non più necessari?
Soluzione
Non si tratta di informazioni che un algoritmo può calcolare in modo affidabile. Il programma ispezionato potrebbe recuperare un elenco di tutte le risorse e fare qualcosa con esse, come consentire all'utente di scegliere tra diverse icone.
Probabilmente la soluzione migliore è cercare tutti i riferimenti all'API di accesso alle risorse prescelta e ispezionarli manualmente. Usando grep
/ sed
potresti essere in grado di ridurre i siti che devi ispezionare manualmente gestendo tutto " facile " quelli in cui viene utilizzata una stringa semplice.
Altri suggerimenti
Di recente ResXManager 1.0.0.41 ha aggiunto una funzione per mostrare il numero di riferimenti a una risorsa stringa .
Non sono riuscito a trovare alcuna soluzione esistente che potesse cercare riferimenti a risorse di stringa nei file XAML e rimuovere quelli inutilizzati in batch.
Quindi ho scritto questo: https://github.com/Microsoft/RESX-Unused-Finder
Cerca in una directory di progetto riferimenti a risorse stringa, quindi visualizza un elenco di quelli per i quali non è stato possibile trovare una corrispondenza. Puoi specificare un modello da cercare in modo che possa trovare riferimenti nei file XAML.
Ho creato un'estensione VS open source gratuita che cerca immagini inutilizzate in un progetto, ho appena pubblicato la prima versione: https://marketplace.visualstudio.com/items?itemName=Jitbit1.VSUnusedImagesFinder
Dato che non ho ancora trovato una soluzione semplice e veloce , ho trovato almeno una soluzione che mi consente di ottenere il risultato che sto cercando, anche se ci vuole del tempo (ideale per una domenica pomeriggio pigra).
La soluzione coinvolge Visual Studio .NET 2010 e ReSharper (sto usando la versione 7.1) e va come segue.
Soluzione dettagliata
1.) Fai clic con il pulsante destro del mouse sul file RESX principale in VS.NET e seleziona " Trova usi " dal menu contestuale:
Questo farà apparire ReSharper " Trova risultati " finestra.
2.) Fai doppio clic su ogni occorrenza nella finestra della soluzione:
Questo aprirà la finestra del codice sorgente con la risorsa.
3.) Rinomina questa risorsa dalla finestra del codice sorgente:
Visualizzerà ReSharper " Rename Resource " finestra di dialogo.
4.) Assegna alla risorsa un nuovo nome con un prefisso univoco . Nel mio esempio questo è " TaskDialog_ " ;:
Rinominerà sia la risorsa che la classe di accesso / wrapper C # generata automaticamente.
5.) Ripeti i precedenti passaggi 2, 3 e 4 per tutte le risorse in " Usages " finestra.
6.) Apri il file RESX nell'editor delle risorse di Visual Studio e seleziona tutti i file senza prefisso:
7.) Ora fai clic su " Rimuovi risorsa " nella parte superiore della finestra o premi semplicemente il tasto Canc :
Finalmente hai un file RESX con solo le risorse usate nel tuo file.
8.) (Opzionalmente) Se disponi di risorse in più lingue (ad es. " Resources.de.resx " per il tedesco), ripeti i passaggi 7 e 8 anche per quei file RESX.
Attenzione
Nota che questo non funzionerà se accedi alle tue stringhe se non attraverso la classe C # fortemente tipizzata e generata automaticamente Risorse
.
Di recente ho creato uno strumento che rileva e rimuove le risorse di stringa non utilizzate. Ho usato le informazioni in questo post come riferimento. Lo strumento potrebbe non essere perfetto, ma fa la parte più pesante e sarà utile se hai un grande progetto con una lunga storia. Abbiamo utilizzato questo strumento internamente per consolidare i file di risorse e rimuovere le risorse non utilizzate (ci siamo sbarazzati di oltre 4.000 risorse su 10.000).
Puoi consultare il codice sorgente o semplicemente installare ClickOnce da qui: https://resxutils.codeplex.com/
Ho avuto un problema simile. Diverse migliaia di stringhe di risorse che avevo creato per una tabella di traduzione, molte delle quali non erano più necessarie o di riferimento per codice. Con circa 180 file di codice dipendenti, non avrei mai potuto esaminare manualmente ogni stringa di risorse.
Il seguente codice (in vb.net) passerà attraverso il tuo progetto alla ricerca di risorse orfane (nelle risorse del progetto , non in tutte le risorse dei singoli moduli ). Il mio progetto ha impiegato circa 1 minuto. Può essere modificato per trovare stringhe, immagini o qualsiasi altro tipo di risorsa.
In sintesi,
- 1) Utilizza il file di progetto della soluzione per raccogliere tutto il codice incluso moduli e li aggiunge in un'unica variabile stringa;
- 2) Passa attraverso tutti gli oggetti delle risorse del progetto e crea un elenco (nel mio caso) di quelli che sono stringhe;
- 3) Esegue una ricerca di stringhe trovando i codici di stringa di risorse nella variabile di testo del progetto combinata;
- 4) Riporta gli oggetti risorsa a cui non si fa riferimento.
La funzione restituisce i nomi degli oggetti negli Appunti di Windows per incollarli in un foglio di calcolo o come array di elenchi dei nomi delle risorse.
edit : esempio di chiamata nel modulo: 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
Uso ReSharper per trovare campi di risorse non utilizzati e quindi rimuoverli manualmente se il progetto contiene una piccola quantità di risorse. Alcuni script brevi possono essere utilizzati se disponiamo già di un elenco di elementi non utilizzati.
La soluzione è la prossima:
- mostra tutti i membri non utilizzati come descritto in questo articolo
- rimuove temporaneamente * .Designer.cs dalle maschere di file generate (ReSharper & # 8594; Opzioni & # 8594; CodeInspection & # 8594; GeneratedCode)
- Commenta o rimuovi anche il commento (che indica che il codice è automatico generato) dalla parte superiore del file Designer.cs allegato al file di risorse.
Avrai un elenco di tutte le risorse non utilizzate, rimosse per rimuoverle da resx.
L'ho preso in considerazione io stesso e credo di avere due opzioni. Entrambi si basano sul fatto che utilizzo un metodo di supporto per estrarre la risorsa richiesta dai file di risorse.
-
Accesso
Aggiungi del codice a " getresource " metodo o metodi in modo tale che ogni volta che si accede a una risorsa, la chiave della risorsa viene scritta in un registro. Quindi prova ad accedere a ogni parte del sito (uno script di test potrebbe essere utile qui). Le voci di registro risultanti dovrebbero fornire un elenco di tutte le chiavi di risorsa attive, il resto può essere cancellato. Analisi del codice
Sto verificando se T4 è in grado di lavorare attraverso la soluzione e creare un elenco di tutti i riferimenti a " getresource " metodo di supporto. L'elenco delle chiavi risultante sarà attivo, il resto può essere eliminato.
Esistono limiti di entrambi i metodi. Il metodo di registrazione è valido solo come il codice coperto dal test e l'analisi del codice potrebbe non trovare sempre le chiavi piuttosto che le stringhe contenenti le chiavi, quindi sarà necessario un lavoro manuale aggiuntivo.
Penso che proverò entrambi. Ti farò sapere come va.
Rinomina la tua directory di immagini corrente e quindi creane una nuova, esegui una ricerca di file all'interno di VS per il percorso dell'immagine, ad esempio "/ content / images", seleziona automaticamente tutte le immagini utilizzate e trascinale nella nuova immagine cartella. Puoi quindi escludere la vecchia directory dal progetto o semplicemente eliminarla.