How do I remove unnecessary resources from my project? - c#

I am working with a very big project (a solution that contains 16 projects and each project contains about 100 files).
It is written in C++/C# with Visual Studio 2005.
One of the projects has around 2000 resources out of which only 400 are actually used.
How do I remove those unused resources?
I tried to accomplish the task by searching for used ones.
It worked and I was able to build the solution, but it broke at runtime.
I guess because enums are used. (IMPORTANT)
How can I make sure that it doesn't break at runtime?
EDIT:
I think one method could be to generate the resource (that is not found) on the fly at runtime (somehow).
But I have no idea about ... anything.
NOTE: It's okay if a few unnecessary resources are still there.

What I would do is write a custom tool to search your source code.
If you remove a resource ID from a header file (i.e. possibly called resource.h) and then recompile and get no warnings: then that's a good thing.
Here is how I would go about writing the app. Take as input the resource file (resource.h) you want to scrutinize. Open the header file (*.h) and parse all the resource constants (Or at least the onces you are interested in). Store those in a hash table for quick look up later.
For each code file in your project, search the text for instances of each of your resource ID's. When a resource ID is used, increment the value in the hash table otherwise leave it at zero.
At the end, dump all the resource ID's that are zero out a log file or something. Then test that indeed you can remove those specified resource ID's safely. Once you do that, then write another tool that removes the specified resource ID's given the results of your log file.
You could write such a tool in perl and it would execute in about 0.3 seconds: But would take days to debug. :)
Or you could write this in .NET, and it would execute a little slower, but would take you an hour to debug. :)

You can use third party plug-in for Visual Studio as ReSharper. This add-in will analyze your C# code and point out unused resources. But it only works with C#.

For C++ projects, check out The ResOrg from Riverblade.
"The Resource ID Organiser (ResOrg for short) is an Add-in for Visual C++ designed to help overcome one of the most annoying (and unnecessary) chores of developing/maintaining Windows applications - maintaining resource symbol ID values"
http://www.riverblade.co.uk/products/resorg/index.html

I've never had one that bad. My method in compiled programs is to use a REXX script which emulates GREP looking for references to source that I suspect is not being used, remove them from the program and see what breaks. I use the REXX script because I can pre-filter the list of files I want to search. Which allows me to do a search across folders and computers.

If your code contains dynamic loading of resources (e.g. via strings) at runtime, then there is no way to automatically determine which resources can be safely removed from the source. A dynamic loading statement could load any resource.
Your best bet is to start with your trimmed down version of the app, run it, and identify which resources are missing when you test it. Then add them back in and retest.

You may want to take a look at the tool Reflector (free), not to be confused with ReSharper (expensive). It can show you which DLLs are dependent on another. Then if you want you may be able to remove the DLL that is not being referenced by anything else. Watch out if you are using dependency injection or reflection which then could break your code without your knowledge.
Reflector:
http://www.red-gate.com/products/reflector/.
This add-in draws assembly dependency graphs and IL graphs:
http://reflectoraddins.codeplex.com/Wiki/View.aspx?title=Graph.

In the "Resources View" of the Solution Explorer, right-click and select "Resource Symbols". Now you get a list where you can see which resources constants are used in the .RC-file. This help you might be a bit on the way to cleanup your Resource.h (although it does not show you which resources are not used in the actual C++ code).

Maybe Find Unused Resources in a .NET Solution helps here? Basically, you'll have to check which resources are used (e.g. by comprehensive code coverage checks) and remove the unused ones.
And probably you should not be afraid by using the trail-and-error approach to cleaning up.

In the Solution Explorer, right click and on a Reference and click on the menu item Find Dependent Code.
If it can't find any dependent code then you can remove this reference from the project. (The Remove operation is also under the right-click menu.)
EDIT: For a large project, the Find Dependent Code operation will take a long time. So since you have 2000 resources and most likely value your time this probably is not a viable option....

For C++ resources, did you try right-clicking the project in "Resource View" and then deleting the ones which do not have a tick mark next to them? It is unsafe to delete unused dialog resources since they are referenced as "enum"s in code (like the following).
enum { IDD = IDD_ABOUTBOX };
..however for all the others it should be safe.

Related

Why are the binary files (exe / dll) different between two builds of the exact same version of a solution? [duplicate]

When I do a clean build my C# project, the produced dll is different then the previously built one (which I saved separately). No code changes were made, just clean and rebuild.
Diff shows some bytes in the DLL have changes -- few near the beginning and few near the end, but I can't figure out what these represent. Does anybody have insights on why this is happening and how to prevent it?
This is using Visual Studio 2005 / WinForms.
Update: Not using automatic version incrementing, or signing the assembly. If it's a timestamp of some sort, how to I prevent VS from writing it?
Update: After looking in Ildasm/diff, it seems like the following items are different:
Two bytes in PE header at the start of the file.
<PrivateImplementationDetails>{guid} section
Cryptic part of the string table near the end (wonder why, I did not change the strings)
Parts of assembly info at the end of file.
No idea how to eliminate any of these, if at all possible...
My best guess would be the changed bytes you're seeing are the internally-used metadata columns that are automatically generated at build-time.
Some of the Ecma-335 Partition II (CLI Specification Metadata Definition) columns that can change per-build, even if the source code doesn't change at all:
Module.Mvid: A build-time-generated GUID. Always changes, every build.
AssemblyRef.HashValue: Could change if you're referencing another assembly that has also been rebuilt since the old build.
If this really, really bothers you, my best tip on finding out exactly what is changing would be to diff the actual metadata tables. The way to get these is to use the ildasm MetaInfo window:
View > MetaInfo > Raw:Header,Schema,Rows // important, otherwise you get very basic info from the next step
View > MetaInfo > Show!
I think that would be the TimeDateStamp field in the IMAGE_FILE_HEADER header of the PE32 specifications.
Could be that the build or revision numbers have changed.

How to include source code in dll?

Short version:
I want my program to be able to (read-only-)access its own source code during runtime. Is there a way to automatically package the source code into the dll during compilation?
Long version:
The background is that when an exception occurs, I want to automatically create a file containing some details of what happened. This file should, among other things, include the source code of the function that caused the problem. I want to send this file to other people by email, and the receiver will most likely not have (or not want to install) Visual Studio, so anything using symbol servers and the likes is out of question. It needs to be a plain text file.
Ideally I would somewhere find the related source code files and just copy out the relevant lines. You can safely assume that as long as I have a folder containing the entire source code, I will be able to locate the file and lines I want.
The best idea I could come up with so far -- and I have not looked into it in much detail because it seems messy to no end -- is to modify the MSBuild files to create a .zip of the source during compilation, and require .dll and .zip to reside in the same folder.
Most of the similar-sounding questions on stackoverflow that I found seem to deal with decompiling .dll files, which is not what I want to do. I have the source code, and I want to ship it together with the .dll in a convenient way.
Update: The really long version
Seems some people are seriously questioning why I would want to do that, so here's the answer: The main purpose of my software is testing some other software. That other software has a GUI. For an easy example, let's say the other software were the standard Windows calculator, then my testcase might look something like this:
calculator.Open();
calculator.EnterValue(13);
calculator.PressButtonPlus();
calculator.EnterValue(38);
calculator.PressButtonEnter();
int value = calculator.GetDisplayedValue();
Assert.That(value == 51);
calculator.Close();
These tests are intentionally written in a very human-readable way.
What I want to do when a problem occurs is to give the developer of the calculator a detailed description of how to reproduce the problem, in a way that he could reproduce by hand, without my software. (In this example, he would open the calculator, enter 13, press plus, and so on.)
Maybe another option would be to have each function calculator.Something() write out an information line to a log, but that would a) be a lot more work, b) only include the test run up to the point where it aborted, and c) bear some risk that writing the line is forgotten in one function, thereby giving an incorrect representation of what was done. But I'm open to other solutions than copying source code.
Take a look at this question: Do __LINE__ __FILE__ equivalents exist in C#?
C++ offers macros (__LINE__, __FILE__, and so on) that replace with the representing information during compile time. This means if you write something like this:
throw new CException(__FILE__);
it will compile to something like this:
throw new CException("test.cpp");
resulting in a hardcoded value. The C# compiler does not offer those macros and you are forced to use reflection to get the information about where the exception has been thrown. The way you can do it is described in the question linked above.
If you are not able to supply .pdb symbols then the default behaviour of Exception.ToString() (or StackTrace.ToString()) will not return you the line number, but the MSIL offsets of the operation that failed. As far as I can remember you can use the Stack Trace Explorer of ReSharper to navigate to the representing code (Not 100% sure about that, but there also was a question here on stackoverflow that mentioned this fact).
You can include copies of the source files as resources.
In the project folder, create a subfolder named Resources. Copy the source files there.
Create in the project a resource file, and then include the source copies you made into it.
Setup a pre-build event to copy the actual source files to Resources folder, so you always have updated copies. In the example I created, this worked well:
copy $(ProjectDir)*.cs $(ProjectDir)Resources
In your code, now you can get the content of the files like this (I suppose the name of the resources file is Resource1.resx:
// Get the source of the Program.cs file.
string contents = Resource1.Program;
The project ended up like this:
Yes, I also recommend packing up the sources in a .zip or whatever during MSBuild, and packaging that .zip with your application/dll. In runtime, when an exception occurs, you get the file and method name like Aschratt describes, extract the file from the .zip and find the method in it.

Can I have global preprocessor definitions in C# library?

In C# you can have conditional compilation by using macros similar to the C/C++ syntax. This would enable the following to happen:
#define MYMACRO
....
#if MYMACRO
//some C# code logic
#else
//some other C# code logic
I need to define some macros in a dedicated file in a C# library project, and I need these macros to be visible inside the entire library, once defined. The problem is that the above code works only for a single file.
Another way I know to work around this, is to add the macros to the build command. This would take care of defining the macros for the entire .dll and I will have the #if - #else checks working wherever I want inside the library. The issues with this approach is that I want to be able to maintain the macros easily. Having them in a file inside the project will be perfect. I'd like to have some comments inside too, so that I will know what each macro is doing. This will not be applicable if I have to pass the macros as build parameters. Another reason is being able to turn a macro on/off by simply commenting it and examining the behavior.
Is there a decent way to achieve my requirement? I'd prefer not to deal with any build automation tools like MSBuild, NAnt or anything like this, still if no other way is possible I'd appreciate an advice which one you consider a better choice.
You #define them for an entire project with Project + Properties, Build tab, "Conditional compilation symbols" setting. This sets the <DefineConstants> element in the project file. You override this property with msbuild by giving it the /property:DefineConstants="MYMACRO" command line option.
I'd also advise putting the macros in the project settings (csproj file) as #Hans Passant suggests.
If you need the defines documented, you could add a documentation file to the solution explaining what the settings mean.
If there aren't too many variants, you could define a new project configuration for each one. That will allow you to pre-configure the necessary list of #defines for each variant, and then simply switch between them from the configuration combo box in the toolbar. If you want to temporarily disable one option, you could duplicate the current configuration and remove the #define, then delete the config later when you've tested it.
The next option I can suggest to make it "easier" (by combining the settings and docs into a single file as you've suggested) would be to use a simple text file (settings + comments) to configure the project, and spend 15 minutes writing a quick c# app to read this file and write the settings it contains into the .csproj file - it's just XML so should be a trivial app to write. You'd be able to easily tweak this file and run your updater app to chnage the project settings. If it's something you will do often, spend 30 minutes on it and add a UI with checkboxes to choose the settings more easily.
The concept you're describing sounds rather odd, though. The point of a library is usually that you have one standardised lump of code that can be shared by many clients, so changing these sort of defines to reconfigure the whole library a lot is not something that I'd expect to need to do very often. Perhaps you have good reasons, but it may be worth reviewing why you need to solve this #define problem.
(e.g. If you have lots of customers who need different variants of the "library", the best approach will be to use configurations (described above) to allow you to build all needed variants in a batch build. If you are just trying out lots of different algorithms/techniques then can you redesign chunks of the library so that you can restrict the impact of most #defines to just to a single .cs file so they no longer need to be global? Perhaps the library shouldn't be in a single dll, or a plug-in architecture is needed to allow you to pick and choose the "modules" that are included within the library)
C# “preprocessor” directives don't work the same as C preprocessor directives. The most important difference for you is that there is no equivalent of #include. It's not needed under normal circumstances, because C# doesn't have (or need) header files. I don't think what you want is possible, unless you somehow create your own preprocessor or read the file with #defines and make them into parameters of msbuild.
But I think it would be easier for you to use more object-oriented approach: encapsulate the different approaches into classes and use them. To specify which one of them to use, you could use dependency injection. That means you would have to ship a DI library along with your library, but I think that's a price worth paying.
Also, this approach would alleviate a problem with conditional compilation: specifying different set of symbols may break the build in unexpected ways.
Using GUI
Open the project in Visual Studio
Right-Click on the project file in the solution explorer go to properties
Go to Build tab and Make sure you select the All Configurations in the configuration drop down
Make sure selected the All Platforms in Platform drop-down
Type the Preprocessor Definitions you want in the Conditional Compilation Symbols text box separated by semicolon
To the Project file
Open the project file in a text editor
Copy and paste this code to end of existing PropertyGroup
<PropertyGroup Condition="'$(VariableName)'=='VarableValue'">
<DefineConstants>PDEF1;PDEF2;PDEF3</DefineConstants>
</PropertyGroup>
If you not required to add a condition, delete the Condition="'$(VariableName)'=='VarableValue'" part
Save the project file and open from Visual Studio
From: https://codeketchup.blogspot.sg/2018/04/how-to-add-project-level-preprocessor.html

C#: Resource file refactoring

Does anyone know of a good tool for refactoring resources in a visual studio 2008 solution?
We have a number of resource files with translated text in an assembly used for localizing our application. But they have gotten a bit messy... I would like to rename some of the keys, and move some of them into other resource files. And I would like those changes be done in my code, and the translated versions of the resource files as well. Maybe a some analysis on what strings are missing in the translated versions, and what strings have been removed from the original as well...
Does anyone know of a good visual studio extension or ReSharper plugin that can help me with this? Right now it is kind of a pain, because I have to first rename the key in the base resource file, then in the localized versions. And then compile to get all the compile errors resulting from the key which now have a different name, and then go through and fix them all... very annoying =/
I just stumbled across this question which prompted me to blog about what I use for this problem here Moving and renaming resource keys in a .resx file.
I have two PowerShell scripts, one which renames a resource key and one which moves a resource key from one resource file to another.
Using these scripts I am able to rename a resource key:
.\RenameResource.ps1 oldKey newKey
And I can move a resource with key “keyName” from a file named “ResourceFile1.resx” to “ResourceFile2.resx”:
.\MoveResource.ps1 ResourceFile1 ResourceFile2 keyName
RGreatEx is suitable when you need to move a lot of strings in code to resources. But in this case it can't help.
There are no such plugin (*this means that I have never seen such and didn't found in google, but there are some localizators which can help to translate to new language - http://www.peoplewords.com/download/ResxEditor.aspx and http://sourceforge.net/projects/resx/ and http://www.resx-localization-studio.net/ and http://madskristensen.net/post/A-NET-resource-editor-application-for-resx-files.aspx). But you easily (may be) can do this without it.
All you need is to write some small tool which will generate common dictionary of strings for a selected language for several selected resx files and store it somewhere. Another tool you need to create is a tool which will generate new resx files (after your changes) using changed resxs as templates and using the dictionary generated by previous tool.
Of course all new and changed strings will be missing but this can be fixed manually. This will take not so much time (especially when you'll add functionality to write a log of missing strings during generation new resx) .
Were looking into Sisulizer to localize our software, and I think it accomplishes what you're asking for (a bit overkill perhaps?)
Seems to be some new features in ReSharper 5 that helps with this
Localizing your Applications with ReSharper 5
This demo shows how ReSharper 5 helps you make strings in your code localizable quickly, without breaking your regular workflow. Working with resource files is no more a developer's nightmare with ReSharper 5.

How To Store Files In An EXE

Alright, so I'm working on programming my own installer in C#, and what I'd like to do is something along the lines of put the files in the .exe, so I can do
File.Copy(file, filedir);
Or, if this isn't possible, is there another way of doing what I am attempting to do?
I wouldn't code my own installer, but if you truely want to embed files into your assembly you could use strongly typed resources. In the properties dialog of your project open up the "Resources" tab and then add your file. You'll then be able to get the file using:
ProjectNamespace.Properties.Resources.MyFile
Then you'll be able to write the embedded resource to disk using:
System.IO.File.WriteAllBytes(#"C:\MyFile.bin", ProjectNamespace.Properties.Resources.MyFile);
Honestly, I would suggest you NOT create your own installer. There are many many issues with creating installers. Even the big installer makers don't make their own actual installers anymore, they just create custom MSI packages.
Use Mirosoft Installer (MSI). It's the right thing to do. Make your own custom front-end for it, but don't recreate the already very complex wheel that exists.
UPDATE: If you're just doing this for learning, then I would shy away from thinking of it as "an installer". You might be tempted to take your "research" and use it someday, and frankly, that's how we end up with so many problems when new versions of Windows come out. People create their own wheels with assumptions that aren't valid.
What you're really trying to do is called "packaging", and you really have to become intimately familiar with the Executable PE format, because you're talking about changing the structure of the PE image on disk.
You can simulate it, to a point, with putting files in resources, but that's not really what installers, or self-extractors do.
Here's a link to Self-Extractor tutorial, but it's not in C#.
I don't know enough about the .NET PE requirements to know if you can do this in with a managed code executable or not.
UPDATE2: This is probably more of what you're looking for, it embeds files in the resource, but as I said, it's not really the way professional installers or self-extractors do it. I think there are various limitations on what you can embed as resources. But here's the like to a Self-Extractor Demo written in C#.
I'm guessing here, but if you are trying to store resources in your application before compilation, you can in the Project Explorer, right click a file you would like to add, chose properties and change the type to Embedded Resource.
You can then access the embedded resources later by using the instructions from this KB:
http://support.microsoft.com/kb/319292
in case you simply want to store multiple files in a single file storage (and extract files from there, interact etc.) you might also want to check out NFileStorage, a .net file storage. written in 100% .NET C# with all sources included. It also comes with a command line interpreter that allows interaction from the command line.

Categories

Resources