Compare compiled .NET assemblies? - c#

Are there any good programs out there to compare to compile .NET assemblies?
For example I have HelloWorld.dll (1.0.0.0) and HelloWorld.dll (2.0.0.0), and I want to compare differences how can I do this?
I know I can use .NET Reflector and use the Assembly Diff plugin. Are there any other good tools out there to do this?

Ways to Compare .NET Assemblies suggests
Commercial:
NDepend
Free:
JustAssembly (only shows differences in API)
BitDiffer (same)
Reflector Diff Add-in (which you've already discovered, but not available anymore)
Existing compare tools like Beyond Compare (commercial) can do this by special configuration. Here's how to do this for Beyond Compare:
Go to Tools → Options
Click New.., select "Text format", click OK
Give it a name (say, EXE, or DLL), and specify the mask as *.exe or *.dll
Click on tab Conversion and select "External program (Unicode filenames)"
Under "Loading", specify the path to ildasm and add %s /OUT:%t /NOBAR (i.e.: C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\ildasm.exe %s /OUT:%t /NOBAR)
Make sure to check disable editing.
Click Save, then Close
Restart BC and open two exe files to compare, it should decompile into ilasm automatically now.
You can also add syntax highlighting to this new format. I plan to send the syntax file to them so that it'll become available to share.

Two ways.
You could ILDASM and diff with classic tools.
Or you could use NDepends, which will cost for that feature.
[Piece to C# bloaters..]

I just had to compare two revisions of the same DLL, which had the same version (I needed to implement a small hotfix, and deploy the DLL in production, but I wanted to make sure that no other changes leaked into code). Ideally, I would want the Assemby Diff add-in to show me the difference, but it does not work (it thinks that I'm comparing a DLL to itself). So this is what I did:
Created two folders to hold disassembled source files.
Used the Reflector's Export option (from context menu) to generate source files from each DLL in the folders created in previous step.
Used the free DiffMerge tool to compare two directories; the tools showed me the modified files and the difference.
It's a bit kludgy, but seems to work. I wish the Assembly Diff add-in worked, though.
UPDATE: The latest version of the Assembly Diff add-in is supposed to fix the issue of comparing two versions of the same assembly. Give it a try.

The tool NDepend offers many features to compare compiled .NET assemblies.
First from the NDepend Start Page click: Compare 2 versions of a code base. This will let you provide older and newer versions of your assemblies.
Then after NDepend has analyzed both older and newer assemblies, you can use the panel Search by Change. It is dedicated to browse assemblies code diff. Notice that:
If source code is available, just right click an element and click Diff Source. In the NDepend options you can plug to NDepend any code diff tool (Visual Studio, Beyond Compare...)
If you don't have the source code and just only the raw assemblies, there is the option Compare older and newer version disassembled with ILSpy. ILSpy v7.0 and upper versions are supported. This menu works on assembly, namespace, type and method level and you can choose to decompile to C# or IL.
Notice also in the screenshot that a CQLinq code query is generated to browse the diff.
from m in Application.Methods
where m.CodeWasChanged()
select new { m, m.NbLinesOfCode }
Many others default diff queries and rules are proposed by default, that will let you browse .NET code diff in a smart way.
Types that used to be 100% covered but not anymore
API Breaking Changes: Methods
Avoid making complex methods even more complex
Avoid decreasing code coverage by tests of types
From now, all types added or refactored should respect basic quality principles
Avoid transforming an immutable type into a mutable one
Heuristic to find types moved from one namespace or assembly to another
Disclaimer: I am one of the developer of the tool.

One more option is LibCheck from Microsoft.
Pretty old console tool for just getting public API diff. I could not run without debugging and retargeting to a more recent .net version. However, it gave me very clear output and I am going to use it later.
Here is an article with screenshots.

Here's a thinking outside the box approach whcih works fine.
Dump your old and new assemblies with dnSpy, dotPeek or JustDecompile into projects.
Create a new Git repo and commit the old assembly code first.
In your local repo folder delete all the files/folders except for ".git" and paste the new assembly files.
Either commit the new changes and view changes on say Github or use a Git viewer like Fork. Easy code comparison for free.

Java has a nice one: Semantic Diff Utilities

Related

Getting a list of all dependencies from a .NET Standard project's csproj

Ever since I've been using the (relatively) new .NET Standard Library project type in Visual Studio, I've been having some problems getting a complete set of DLL files that are required by my project.
The problem is usually limited to 3rd-party libraries which I reference as NuGet packages. I've noticed that these don't get copied to the output folder of my project when I build it. This didn't use to be the case in classic project types.
While I can appreciate the de-cluttering effect that this change has brought for .NET Standard projects, I'm now faced with a problem. I sometimes absolutely need to be able to get the entire list of all files that my project depends on!
I have several different cases, where I might require this list for one reason or another, but the one I believe is most crucial for me, is when I want to gather these files from the csproj itself, right after it's built. In there, I have a custom MSBuild <Target> which should take all the files from the output dir and zip them together for distribution. The problem is, I'm missing all the files that come from NuGet dependencies, because they're not there!
How can I solve this in a general (i.e. not project-specific) way?
UPDATE
There's this deps.json file that contains basically all I'm after and then some. It's just a matter of extracting the relevant information and find the files in the local NuGet cache. But that would involve writing a specialized app and calling it from my target. Before I start writing one myself... Is there something like this already out there somewhere?
I followed this answer and it sort of works.
The suggested thing was to include the following into my csproj:
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
My main concern is that it also outputs some other DLLs from the framework (such as System.Memory.dll and System.Buffers.dll, among others), which I didn't expect. But maybe that's a good thing. They do seem to be dependencies, just not direct ones. I'll see how it plays out.
If it turns out ok, my only wish would be that this directive was more prominently displayed in project settings (as a simple checkbox, maybe?) so I wouldn't have to hunt the web to find it.

Go to source in a multi solution enviroment in Visual Studio 2019

We have a scenario like this:
We have ~100 solutions containing 10 projects each.
Each solution copies its artefacts (i.e. its 10 dlls) to a shared single folder like C:\code/assemblies.
If I develop something for feature X, I'll open up SolutionX.
The source for all solutions/projects is local in a single Monorepo C:\code.
During debugging, when the method/class/whatever is implemented in project Y, it opens the corresponding file (which is nice). So there must be information available how to get to the source.
But when developing, I cannot navigate to the implementation e.g. by using F12 ("go to definition") but just get the signatures gathered from meta data. I'd like to have the same experience like during debugging.
So right now I open up a Visual Studio Code, open the folder containing the sources and do a "search in files".
Any better ideas?
N.b. Resharper is not an allowed option. Also doesn't play nice with Postsharp.
N.b. I don't know if it is important but all except one solution start an external program (the shell), since all except one solution contain only dlls.
I have done similar in Old project.
You can use Symbol with Visual Studio 2019. Simple steps can be:
A. Generate Symbols for projects :
In Solution Explorer, select the project.
Select the Properties icon (or press Alt+Enter).
In the side pane, choose Build.
In the Configuration list, choose Debug or Release.
Select the Advanced button.
In the Debugging information list, choose Full, Pdb-only, or Portable.
Refer for more information:
Set debug and release configurations in Visual Studio
Publish symbols for debugging
B. Use Symbol in Visual Studio:
In Visual Studio, open Tools > Options > Debugging > Symbols (or Debug > Options > Symbols).
Under Symbol file (.pdb) locations,
To use the Microsoft Symbol Servers or NuGet.org Symbol Server, select the checkbox.
To add a new symbol server location,
Select the + symbol in the toolbar.
Type the URL (http), network share, or local path of the symbol server or symbol location in the text field. Statement completion helps you find the correct format.
Tools - Options - Debugging - Symbols page
For more Details refer:
Configure symbol locations and loading options
I think you should analyze project dependencies (for example with https://www.ndepend.com/docs/visual-studio-dependency-graph ) and cluster your projects in less Solutions
Edit : I am editing this answer based on your comment. I think you are looking for two use cases
Peek into the source code of referenced binaries
Navigate to the source and then edit them in place
To achieve option (1)
In Visual Studio 2019, use the built in decompiler to help you with navigating to code outside of the solution. This is an experimental feature as of May 2020. By default this is disabled and you should enable it. Once enabled the F12 navigation will decompile and allow you to peek into the source code.
On the other side, the more you relax the compilation the better the decompilation. Meaning, you can turn off optimisations (if any). This doesn't have to do anything with symbol generation options.
If you are using visual studio 2017 (or) less, the same can be achieved by Telerik Just Decompile plugin (free). Check the feature View decompiled code in tabs
To Achieve option (2) :
You should reference source files rather than binaries, because you won't get the natural in-place edit with referencing binaries. There are always going to be caveats irrespective of the solution you choose. Referencing source can be done using the "Add as link" feature in Visual studio, where the source code belong to one solution and can be referenced as link (something like windows shortcuts) in all the other solutions. (https://andrewlock.net/including-linked-files-from-outside-the-project-directory-in-asp-net-core/). If you are referencing source, you need to remove the binary references.
And you also have to decide from an architectural standpoint on how this changes the way people develop and commit code. The point of referencing binaries is to make sure they are not edited for convenience, but that depends on the nature of the development team purely.
Conclusion
From a best practices standpoint, you either have to reference binaries and don't allow them to be edited (or) you allow source references and edit in place. But that depends purely on what you want to achieve.

How to deploy "extension method" within a VSIX extension?

Due to the wording (many meanings of "extension" and "method"), I am utterly unable to find any information about my question on the interwebs. So I am asking here:
Is it possible to deploy "extension methods" with a VSIX extension?
Clarification:
By "extension method" I mean something like
public static string SomextExtension(this string s, string p) {
retrun s + p;
}
By VSIX extension I refer to a custom extension, that gets installed via a
SomeCoolExtension.vsix
The goal is:
A user installs the VSIX, gets a few features (mainly custom code generators in my case) and additionally has access to "Hello".SomeExtension(" World"); within their source code.
I am slowly thinking this just isn't possible as I have tried everything I could come up with and as stated in the beginning, it is virtually impossible to search for it on googls.
If it really is impossible, I would at least love to understand why.
So a simple "no" might be a valid answer, but if you could elaborate, that would put my coding soul to rest :-)
Specs: I am using VS2017 and the new "Visual Studio AsyncPackage", but if you know an answer for older version, I sould be happy to try them.
You can use both approaches:
An extension (.vsix) provides the greatest flexibility, because it can provide commands (buttons on menus, context menus and toolbars) that, on demand by the user, can 1) Insert code in the active document 2) Add files with code or other assets 3) Add references to Dlls that the extension can deploy in the source folder of the project, etc. Also, it can do all that not only on demand, but automatically watching events and examining if some conditions are met, for example, a solution is created, or it is loaded, a project is added, it already contains a code file or not, it already has a reference or not, etc. Needless to say, all this flexibility comes from some complexity.
A NuGet package can add DLLs to the references or code files to a project, it can execute a PowerShell script when the NuGet package is added to a project that can modify the project, it can modify the build process adding new MSBuild targets/tasks (being the Microsoft.VSSDK.BuildTools NuGet package to create a VSIX extension the prime example). It is a one-time operation during installation on a project. After that, no events, no commands, etc. but for most scenarios is much simpler.

Antlr4 C# targets and output path of generated files

I have a C# solution with an Antlr3 grammar file, and I'm trying to upgrade to Anltr4. It turns out the grammar was the easy part (it became better, and one third the size!). Generating the parser turned out to be the tricky part.
In the old solution I merely ran AntlrWorks to update the lexer and parser .cs files when the grammar file changed. The lexer and parser were included directly in the same project as the grammar so the framework around the parser could make use of them directly.
With the Antlr4 targets for C# I noticed that (at least by default) the output path of the generated Parser C# classes is in the intermediate directory, e.g. obj\Debug. This means I can't use the parser directly in the same project. Am I supposed to change the output path if I want the generated source usable in my sln? Don't I want it in my sln?
I tried making a separate project for the parser generation, that is, a project containing only the grammar file. When this project is built using the Antlr4 targets, the resulting assembly can be referenced from projects needing the parser classes. However, if this project is included in the solution I still don't get any intellisense in visual studio since it bases its intellisense on source files for loaded projects, so it is still not quite usable. The only way I could get it working properly was to build then unload the parser project, and have other projects reference it as an assembly file rather than a project.
EDIT:
After looking on the antlr-interest list I found this thread indicating that the problem with intellisense may be Resharpers fault. If this is the case, then my question is rather how to keep using both Antlr4 and Resharper in my solution?
https://groups.google.com/forum/#!topic/antlr-discussion/QSuJXphaBDg
I found an extension for Resharper: ReSharper.ExternalCode.
Tip for Antlr: add obj\Debug in Resharper -> Code Inspection -> External Code and reload solution.
It's works for me.
There is an easy way to get the best of both Antlr 4 and Visual Studio. You are on the right track in having a separate grammar project and implementation project, but you are missing a couple steps.
Follow these steps to get the Intellisense working
In Visual Studio, go to Tools -> Extensions and Updates and search the Online section for "ANTLR Language Support" by Sam Harwell.
This does a few things:
Adds Templates for the combined grammars.
Adds Syntax Highlighting
Adds an MSBuild target for the grammar to generate the parser.
In your solution, set up your project structure like this:
Solution
Grammar Project
ANTLR 4 Combined Grammar
Implementation Project
Folder for Links to Generated files
Listener Implementation Class
Write and Compile your grammar.
In your folder for the Links to Generated Files, Right-Click the folder and click Add -> Existing Item
Browse to Grammar Project\obj\Debug and select all the generated parser files.
This next step is important. On the Add button there is a little drop-down arrow. Click the drop-down arrow and click "Add As Link".
This will add the generated files to the implementation project using a symbolic link instead of a direct copy.
This gives the added benefit of not having to remove and re-add the parser files if you have to change your grammar later.
Intellisense should work now for your generated parser classes, and you don't
even have to disable ReSharper.
You are encountering a known bug with ReSharper. The ANTLR 3 and ANTLR 4 C# build integration is reliable, and uses long-established patterns that Microsoft uses with other languages and code generation tasks. Your options are:
Stop using ReSharper
Get the ReSharper authors to address the lack of support for this feature, or
Modify the ANTLR 4 target to work around the limitation in ReSharper, which will introduce other problems into the build which may or may not be acceptable for your use.
Option 1 is certainly the least expensive, and most likely to provide reliable long-term support for your projects.

.NET Dependency Management and Tagging/Branching

My company is having trouble figuring out the best way to manage our builds, releases, and branches... Our basic setup is we have 4 applications we maintain 2 WPF applications and 2 ASP.NET applications, all 4 of these applications share common libraries, so currently they are all in one folder /trunk/{app1, app2, app3, app4}.
This makes it very hard to branch/tag a single application because you are branching all 4 at the same time, so we would like to separate it out into something like {app1,app2,app3,app4}/{trunk,tags,branches} but then we run into the issue of where to put the shared libraries?
We can't put the shared libraries as SVN externals because then when you branch/tag the branch is still referencing the trunk shared libs instead of having them branched as well.
Any tips? Ideas?
We are currently using svn and cruisecontrol.net.
EDIT: The shared libraries are changing often as of right now, which is why we can't use them as svn externals to trunk, because we might be changing them in the branch. So we can't use them as binary references.
Its also very hard to test and debug when the libraries are statically built instead of including the source.
I guess it all depends on how stable the shared libraries are. My preference would be for the shared libraries to be treated as their own project, built in CruiseControl like the others. Then the four main applications would have binary references to the shared libraries.
The primary advantage with this approach is the stability of the applications now that the shared libraries are static. A change to the libraries wouldn't affect the applications until they explicitly updated the binaries to the newer version. Branching brings the binary references with it. You won't have the situation where a seemingly innocuous change breaks the other three applications.
Can you clarify why you don't like branching all four applications at the same time?
This makes it very hard to branch/tag a single application because you are branching all 4 at the same time
I usually put all my projects directly under trunk as you are currently doing. Then when I create a release branch or a feature branch, I just ignore the other projects that get carried along. Remember, the copies are cheap, so they're not taking up space on your server.
To be specific, here's how I would lay out the source tree you've described:
trunk
WPF1
WPF2
ASP.NET 1
ASP.NET 2
lib1
lib2
branches
WPF1 v 1.0
WPF1
WPF2
ASP.NET 1
ASP.NET 2
lib1
lib2
WPF1 v 1.1
WPF1
WPF2
ASP.NET 1
ASP.NET 2
lib1
lib2
lib1 payment plan
WPF1
WPF2
ASP.NET 1
ASP.NET 2
lib1
lib2
We are kicking off an open source project to try and deal with this issue. If anyone is interested in commenting on it or contributing to it, it's at:
http://refix.codeplex.com
I agree with #Brian Frantz. There's no reason to not treat the shared libraries as their own project that is built daily and your projects take binary dependency on the daily builds.
But even if you want to keep them as a source dependency and build them with the app, why wouldn't the SVN externals approach work for you? When you branch particular app, there's no need to branch the shared library as well, unless you need a separate copy of it for that branch. But that means, it not a shared library anymore, right?
I've tried solving this problem several ways over the years, and I can honestly say there is no best solution.
My team is currently in a huge development phase and everyone basically needs to be working off of the latest and greatest of the shared libs at any given time. This being the case we have a folder on everyone's C: drive called SharedLibs\Latest that is automatically synced up with the latest development release of each of our shared libraries. Every project that should be drinking from the firehose has absolute file references to this folder. As people push out new versions of the shared libs, the individual projects end up picking them up transparently.
In addition to the latest folder, we have a SharedLibs\Releases folder which has a hierarchy of folders named for each version of each shared lib. As projects mature and get towards release candidate phase, the shared lib references are pointed to these stable folders.
The biggest downside to this is that this structure needs to be in place for any project to build. If someone wants to build an app 10 years from now, they will need this structure. It is important to note that these folders need to exist on the build/CI server as well.
Previous to doing this, each solution had a lib folder that was under source control containing the binaries. Each project owner was tasked with propagating new shared dlls. Since most people owned several projects, things often fell through the cracks for the projects that were still in the non-stable phase. Additionally TFS didn't seem to track changes to binary files that well. If TFS was better at tracking dlls we probably would have used a shared libs solution / project instead of the file system approach we are taking now.
Apache NPanday + Apache Maven Release
... might solve your problems
It gives you dependeny management (transitive resolving), strong versioning support, and automatic tagging/branching on 14+ version control systems, including SVN.
Give me a hint, if I should elaborate more.
I think there is no way you can avoid versioning and distributing your shared libs as separate artifacts, but Maven helps you alot doing that!
And you can allways do tricks to get it all opened in one Solution :-)
A sample workflow:
Dev 1 build A locally using Maven
Checks in sources
Build server builds A and deploys so-called SNAPSHOT-Versions to Repository Manager (e.g. Nexus)
Dev 2 two loads B, NPanday will automatically resolve the A-libs from the Repository Manager (No need to get the source and build)
Dev 1 wants to release A: Maven Release creates a branch or a tag with your source, finalizes the Version (removing SNAPSHOT) and deploys the artifacts to a Repository Manager.
Dev 2 can now upgrade B to use the final release of A (change entry in xml, or use VS-addin to do so)
Now Dev 2 can release B, again with automatic creation of tag or branch and deployment of built artifacts.
If you want to provide zipped packages as output from your build, Maven Assembly Plugin will help you do that.
You can use Apache/ IVY in standalone mode.
http://ant.apache.org/ivy/history/latest-milestone/standalone.html
I need to emphasize "stand alone" mode. If you google for examples....you will find alot of (not standalone) ones.
Basically, IVY works on this premise.
You publish binaries (or any kind of file, but I'll say binaries from this point forward).....as little binary-packages.
Below is PSEUDO code, do not rely on my memory.
java.exe ivy.jar -publish MyBinaryPackageOne.xml --revision 1.2.3.4 (<< where the .xml refers to N number of files that make up the one package.))
"Package" simply means a group of files. You can include .dll and .xml and .pdb files in a package (what I do with a DotNet build of assemblies). Or whatever. IVY is file-type agnostic. If you want to put WordDocs up there you could, but sharepoint is better for documents.
As you make bug fixes to your code, you increment the revision.
java.exe ivy.jar -publish MyBinaryPackageOne.xml --revision 1.2.3.5
then later you can retrieve from IVY what you want.
java.exe ivy.jar -retrieve PackagesINeed.xml
PackagesINeed.xml would contain information about the packages you want.
something like
"I want version '1.2+ of the MyBinaryPackageOne"
(defined in xml)
As you build your framework binaries...you PUBLISH to IVY.
Then, as you develop and build your code...you RETRIEVE from IVY.
In a NUTSHELL, IVY is a repository for FILES (not source code).
Ivy then becomes the definitive source of your binaries.
None of the "Hey, Developer-Joe has the binaries we need" kind of bull-mess.
.......
Advantages:
1. You do NOT keep your binaries in source control. (and thus do not BLOAT your source control).
2. You have ONE definitive source for binaries.
3. Through xml configuration, you say which versions you need for a library.
(In the example above, if version 2 (2.0.0.0) of MyBinaryPackageOne is published to IVY (let's assume with breaking changes from 1.2.x.y)...then you are OK, because you defined in your retrieve (xml configuration file) .. .that you only want "1.2+". Thus your project will ignore anything 2+...unless you change the configuration package.
Advanced:
If you have a build machine (CruiseControl.NET for example)....you can write logic to publish your (newly built) binaries to IVY after each build.
(Which is what I do).
I use the SVN revision as the last number in the build number.
If my SVN revision was "3333", then I would run something like this:
java.exe ivy.jar -publish MyBinaryPackageOne.xml --revision 1.2.3.3333
Thus whenever retrieve the package for revision "1.2.3+" .... I'll get the latest build.
In this case, I would get version 1.2.3.3333 of the package.
It's sad that IVY was started in 2005 (well, that's the good news)...but that NUGET didn't come out til 2010? (2011?)
Microsoft was 5-6 years behind on this one, IMHO.
I would never go back to putting binaries in source control.
IVY is very good. It is time proven. It solves the problem of DEPENDENCY management.
Does it take a little bit of time to get comfortable with it?
Yep.
But it is worth it in the end.
My 2 cents.
.................
But idea #2 is
Learn how to use NUGET with a local (as in..local to your company) repository.
That is the about the same thing as IVY.
But having looked at NUGET, I still like IVY.

Categories

Resources