In this post, you will learn to identify used and unused resources in VS project resources.resx file.
If you often use project resources in a Visual Studio project, be it VB or C#, eventually you will end up with a big resource file (e.g., Resources) containing many unused items. This is because, when you remove the code that uses the resource, very often, you will forget to remove the actual resource item.
There are solutions to this problem such as using commercial code refactoring tool or making some minor modifications to Resources.Designer.vb/Resources.Designer.cs and relying on the compiler to generate warnings about unused resources. In this post, I choose to take a different approach: use a batch script.
My complete batch script will accept four parameters from the command line, listed from left to right:
- Path to the VB.NET source code files, e.g., WindowsApplication1*.vb
- Name of project resource file, e.g., WindowsApplication1My ProjectResources.resx
- Name of file where all resources’ usage are written, e.g., all_resources.txt
- Name of file where all unused resources are written, e.g., unused_resources.txt
It makes use of the FOR
extended syntax (FOR /F
) to parse the resource file and FINDSTR
to find where all the resources are referred to. It will only work properly with VB source code files, where most developers often use My.Resources.XXXX to access the resources. As FINDSTR
simply performs a string
search, the batch script will not care about code that are commented out, as well as resources that are accessed not by using the VB’s My
namespace. If you want to use this with C# source code, you’ll need to edit the call to FINDSTR
to match your method of accessing the resources, e.g., Project1.Resources.Resource1
instead of My.Resources.Resource1
.
The rest of this post will analyse some interesting points I encountered when writing it – hope this will be useful for those having similar problems.
Batch Script – Powerful Despite Being Crude
Many people may think that batch script is a thing of the past, since there are so many alternatives today – Windows PowerShell, Perl, or a .VBS file. Yet sometimes, I still use it due to its powerful but simple nature. Take a look at the code to search for the resource:
FOR /F "tokens=*" %%a IN (%TMPFILE%) DO (
………
FINDSTR /S /P /N /C:"My.Resources.%%c" %SRCPATH% >> %OUT_ALLTOKENS%
1 and above if it was not found.
IF ERRORLEVEL 1 (
………
)
………….
)
)
The call to FOR /F
and FINDSTR
can easily translate into 10-20 lines of .NET code, unless you use some existing text processing libraries. Here, almost everything is done, just simply remember the syntax, available via FOR /?
or FINDSTR /?
.
Another example is how to generate a random file name:
:GETTEMPNAME
set TMPFILE=%TMP%mytempfile-%RANDOM%-%TIME:~6,5%.tmp
if exist "%TMPFILE%" GOTO :GETTEMPNAME
The equivalent .NET code would be:
string filename = Path.GetTempFileName()
However, batch scripts are still very crude. For example, although Windows XP batch scripts allow the use of block
statement via (……..), don’t expect everything to work as they do in a modern programming language. The following would cause a problem:
IF (%1) == () (
ECHO Missing first parameter: path to the VB.NET source code files
(e.g. WindowsApplication1*.vb)
EXIT /B 1
) ELSE (
SET SRCPATH=%1
)
Execution would terminate shortly upon reaching ECHO
, without any indication why. I believe it would take many people some time to figure out what causes it and fix it. The following will work:
IF (%1) == () (
ECHO Missing first parameter: path to the VB.NET source code files,
e.g. WindowsApplication1*.vb
EXIT /B 1
) ELSE (
SET SRCPATH=%1
)
Also, the above example demonstrates how to check for missing parameter. This would have made more sense in C# or VB.NET, just compare against an empty string
(e.g. “”).
There are many other useful code snippets in this batch script, for example, how to use delayed environment variable expansion, or how to use double quotes as delimiters in FOR /F
. I will not explain it in details – the code is well commented, take some time to study it yourself.