I am compiling a project with Visual Studio 2013 against .NET 4.5 and then checking it again with ILDASM.
What I noticed is that the build in Release still contains method names and variable names, I thought these should be removed in a release-build or do I need an obsfuscator to do that?
You need an obsfuscator to hide method and member names, local variable names should be stripped by the compiler, but anything that can turn up using reflection is preserved that includes class and interface names, public and private methods, public and private fields.
As for method names, the compiler doesn't know if your assembly will be used or not in another project, so the preservation of method names is logical. Though variable names can't be used anywhere than in the method where they're defined, I guess it is useful for debugging (be it Debug or Release) and they really take insignificant space.
And my advice, don't use obfuscator, unless your application contains security critical codes (and then, I'd still advise obfuscating just this code, not the other methods). It is way better for debugging and reading exceptions.
Related
This question already has answers here:
Removing all unused references from a project in Visual Studio projects
(16 answers)
Closed 2 years ago.
In relation to this question: "Remove unused references (!= "using")", I would like to know if there is a tool for removing unused classes, structs, delegates, etc from a Visual Studio solution.
Scenario:
I have an unorganised Visual Studio Solution which consists of 1000's of:
Native method imports
Structures
Delegates
Enumerations
Rather than trawling through each file clicking "Find All References" and determining if the code is being used somewhere, is there any mechanism by where I can simply remove redundant code files easily?
Example:
//This class contains a method called getRandomValue which returns type RANDOM
public class NativeMethods
{
[DllImport("random.dll")]
public static extern RANDOM getRandomValue();
}
//This is the RANDOM object as referenced by getRandomValue();
[StructLayout(LayoutKind.Sequential)]
public struct RANDOM
{
uint a;
uint b;
uint c;
}
//This is redundant since nothing is referencing it.
[StructLayout(LayoutKind.Sequential)]
public struct MESSAGE
{
IntPtr sender;
IntPtr recipient;
char[] mText;
}
Note to self:
My gut feeling is that this is going to be tricky since unlike Java, object names do not have to be identical to the file name, and multiple object declarations can reside within a single file, however in this instance (my scenario) every object is declared within its own file (with an identical name).
ReSharper is the best choice to clean up your code.
You can use it for free thanks to ReSharper Early Access Program.
There are several tools that you can use to do this:
FxCop (free)
NDepend (paid)
Resharper (paid)
FxCop will only find unused internal and private code. Of course if you make sure you only publicly expose code that needs to be accessible outside your assembly, then that should be good enbough.
As pointed #Ergwun the tool NDepend can help to find unused methods, fields and types.
To elaborate a bit, NDepend proposes to write Code Rule over LINQ Query (CQLinq). Around 200 default code rules are proposed, 3 of them being dedicated to unused/dead code detection
Basically such a rule to detect unused method for example looks like:
// <Name>Dead Methods</Name>
warnif count > 0
from m in Application.Methods where !m.MethodsCallingMe.Any()
select m
But this rule is naive and will return trivial false positives. There are many situations where a method is never called yet it is not unused (entry point, class constructor, finaliser...) this is why the 3 default rules are more elaborated:
Potentially dead Types (hence detect unused class, struct, interface, delegate...)
Potentially dead Methods
Potentially dead Fields
NDepend integrates in Visual Studio 2022, 2019, 2017,2015, 2013, 2012, 2010, thus these rules can be checked/browsed/edited right inside the IDE. The tool can also be integrated into your CI process and it can build reports that will show rules violated and culprit code elements. NDepend has also a VS Team Services extension.
If you click these 3 links above toward the source code of these rules, you'll see that the ones concerning types and methods are a bit complex. This is because they detect not only unused types and methods, but also types and methods used only by unused dead types and methods (recursive).
This is static analysis, hence the prefix Potentially in the rule names. If a code element is used only through reflection, these rules might consider it as unused which is not the case.
In addition to using these 3 rules, I'd advise measuring code coverage by tests and striving for having full coverage. Often, you'll see that code that cannot be covered by tests, is actually unused/dead code that can be safely discarded. This is especially useful in complex algorithms where it is not clear if a branch of code is reachable or not.
Disclaimer: I work for NDepend.
I need to use a iOS build setting in Unity3d that strips unused classes from bytecode but as it uses static analysis to discover which to remove- so any classes resolved through reflection will not be excluded from removal unless explicitly added to an exclusion list. I managed to remove all uses of reflection in my own code, but Mono itself seems to use a reflection based configuration to do a bunch of stuff and I've already added about a dozen classes to the exclusion list but now I'm to the point where exceptions are not giving any clues as to what class needs to be excluded for them to work.
My question is, is it possible to get a precise list of all the classes (with source assembly and namespace) resolved through reflection throughout every assembly that the application uses, and how would you go about it? I have Visual Studio 2012 and while I know it has powerful debugging tools I don't know how I would use them to this end.
Thanks.
The short version
You can't as there is no way to find all lookups via reflection using static analysis.
The long version
Just think of the following example: I write code that selects a class depending on user input, e.g. in pseudo code:
string action = ... ; // get some user input here, e.g. "Fire"
string clazz = "Do" + action;
var obj = Activator.CreateInstance("MyActions", clazz);
As you can see the actual full class name is not occuring anywhere in the code. So you would need to execute the code in every possible way to find out which values the clazz variable could assume. Therefore you cannot find out which classes this code would access via reflection.
Further Questions
What exact API from Mono are you using and what kind of exceptions are you getting? Maybe there is some alternative that could be used for your purpose.
I use VS2012 and ReSharper 7 to write C# code. My projects are rarely so large or complicated as to require thinking about granular access levels. It's usually easier for me to just make everything public, instead of spending time and effort to figure out what should be open to access by what. In any case, I am the only one using my code.
I realize this does not apply to everyone, and I realize that access modifiers are important features of the language and should be used carefully. But in my current situation, it doesn't matter and everything might as well be public (in practice I do make them public). I suspect this applies to many other programmers, especially non-enterpise ones.
However, the tendency of VS2012 is to default to the lowest access level. For instance, if I add a new field by typing int id_number;, the moment I put the semicolon in private is added to the field, then I have to go back and change it to public if that was my intention (it usually is).
How can I make VS/ReSharper generate classes, fields, methods and so on with the highest possible access level (essentially, make everything public)?
You can't.
Resharper adds private, because that's the default if you wouldn't specify any access modifier.
So, Resharper doesn't change the access level of your field. It just makes it explicit and because of that, Resharper doesn't have any functionality to change the access level automatically.
But you could easily use automatic properties. There even is a live template for it. Just type prop and hit TAB.
For classes and interfaces (typing class MyClass will cause ReSharper to recongnize "class" as a shortcut, and insert the template class MyClass { } as opposed to public class MyClass { }) it's possible to edit the template through ReSharper -> Template Explorer.
Things such as generated methods which are created by Extract... commands appear to be determined by Visual Studio's code snippets. The location of these can be found in the Code Snippet Manager (Ctrl+K, B). Each snippet is an XML file, this MSDN page describes editing them.
I'm working with some, unfortunately largely undocumented, existing code and I'm having trouble understanding how it calls upon the methods of the plugins it loads.
My aim at the moment is simply to step into one of the methods loaded via the plugin manager, as it's causing an exception. However I had to rebuild the pluginManager from the source to get debug symbols and when I reference this new DLL version the compiler throws up arms.
The code appears to load the plugin into plug.Instance and then access the specific methods like so plug.Instance.ReturnLeaNumber();
This compiler error makes sense, because it doesn't know the details of the plugins. What confuses me is how the compiler ever knew these where valid before run time, when no plugins are initialized. I can step through the code that doesn't work now with the older DLL!
This is an example of where the program loads up a plugin.
plug = GenericServicePlugins.AvailablePlugins.Find(Application.StartupPath + "\\Dlls\\SchoolInterface.dll");
// Compiler doesn't like this next line anymore though
plug.Instance.Initialize(null, null);
If there are any differences between my rebuilt library and the previously working one, I can't tell how as the versions match up with the ones in our source control. Would appreciate some advice on where to start looking!
public interface IGenericPluginMasterInterface
{
String returnName();
void Initialize(ExceptionStringResources.Translate ExceptionStrings);
Object ExecuteFunction(String macAddress, bool log, String functionName, LoginCredentials logonCredentials, WebConfiguration webConfig,
Int64 dataLinkId, DataLinkParam[] dataLinkParams, String dataName,
DataParam[] dataParams, Object[] additionalParams);
}
Rest of Manager code on PasteBin
How does the compiler know about these plug.Instance.Method() methods before runtime?
Edit:
I've not quite worked this out yet, but there was a "PluginsService" file I missed which partly mirrors the "GenericPluginServices".
I think this error could have been caused when I removed parts of this class that related to an now defunct plugin, which I am looking into. However I figured posting this other code snippet would help the question.
PluginService.cs code
GenericPluginService code
Find returns AvailablePlugin, so .Instance is of type IGenericPluginMasterInterface; if so, indeed; that .Instance.ReturnLeaNumber() can't possibly work...
The only way that could work (without introducing some generics etc) is if .Instance actually returned dynamic. With dynamic the name/method resolution is happening at runtime. The compiler treats dynamic very deliberately such as to defer all resolution to runtime, based on either reflection (for simple cases) or IDynamicMetaObjectProvider (for more sohpisticated cases).
However, if the code you have doesn't match what was compiled, then: we can't tell you what it was. IMO, the best option is to get hold of the working dll, and look at it in reflector to see what it is actually doing, and how it is different to the source code that you have.
Actually, strictly speaking it could still do that with the code you've pasted, but only if plug is typed as dynamic, i.e. dynamic plug = ...
I was debugging some code in Visual Studio 2005, when I noticed that the IDE was not hitting breakpoints in a particular generic class. I could manually step into the class, but the tool-tips shown when hovering over references contained nothing but memory addresses instead of the normal friendly tool-tips.
It turns out that the problem is caused by the name of the file (!). Specifically, when the file name contains a ` (backtick, backquote), the debugger will not load the symbols for that file. The workaround is to rename the file.
I was using a backtick in the first place to represent the cardinality of a generic type:
Foo.cs contains a non-generic type (e.g. Foo)
Foo`1.cs contains a generic type with a single type parameter (e.g. Foo<T>)
Foo`2.cs contains a generic with two type parameters (e.g. Foo<T,U>)
This bug (is it?) occurs in Visual Studio 2008 as well.
Can anyone explain this behavior?
I was under the impression that behind the scenes generic types are compiled into types that have backticks in their names. Say you had List<int> and List<string>, behind the scenes you'd have two classes. One would be System.Collections.Generic.List'1 and the other System.Collections.Generic.List'2. These classes may be generated and stored in files of the same name (with .cs extension).
I'm guessing that if you stick backticks in your file name you're going to be messing with this mechanism.
I am speculating a bit here as I haven't researched it, but it could be something for you to research? :)
Good luck
EDIT - Had to use apostrophes instead of backticks as they're reserved symbols in this editor :)