views:

185

answers:

4

My client has a compiled ASP.NET 2.0 application that was compiled & deployed a year ago. They also have 4 versions of source code projects/solutions not under source control (stored on previous developer's workstation file system). None of the file dates appear to match one another.

Is there any way to determine which (if any) of those versions is the one actually deployed to the production web site?

+1  A: 

If your project directories contain build artifacts such as DLLs and EXEs, you could check the version numbers and compare with those in production. Even if you don't get an exact match, you'll see what might be closest.

Vinay Sajip
Version numbers can be arbitrary. You need to disassemble the artifacts and go from there to be certain.
Saul Dolgin
Yes they can be arbitrary, but you could be a *long* time disassembling those artifacts. So my answer is pragmatic, but YMMV.
Vinay Sajip
+1  A: 

.NET Reflector is a handy tool to see what code is being in use at a given server.

David Hedlund
+4  A: 

If I were in your situation, I would compile each of the 4 separate source projects one at a time... Then run the diff add-in for .NET Reflector to see if you have a match with the production assembly. If not, compile the next source project and try the diff again.

Saul Dolgin
+1 for the link to the diff add-in.
Vinay Sajip
+3  A: 

I've done this on client projects multiple times and use Reflector, like other commentors. This kind of thing happens more often than it should. For instance, when someone leaves the development team suddenly. On one project, my team of contractors was called in after the ENTIRE development team left and we had to follow this procedure on every single piece of code running in production to be sure of what we actually had on our hands.

The way I deal with it is this by taking EVERY version of the compiled code that's available into a separate area in the filesystem. This includes the version that's in source control or off of the development workstation. This is important because Reflector sees the IL and not the actual original source, and you want to compare apples to apples.

I use the FileDisassembler for Reflector to decompile each of the binaries into a separate folder. I end up with a structure that looks something like this:

ProjectXyzReconciliation
|-production
|-staging
|-test
|-qa
|-devworkstation
|-sourcecontrol
|-reconciled (this is what will eventually go back in source control)

I then use WinMerge (but have used other merge/comparison tools equally well) to compare the directories and merge them into the "reconciled" folder. I usually populate that with what's running in production to start with and compare every other version against it.

The first pass is really just to see what's different and decompiling out to files lets you use tools like WinMerge to get reports of what's actually different for making decisions.

Sometimes, this process yields one or 2 changes that are easily traceable to bugs in the bug tracking database or emails, etc. and decisions can be made as to whether it should go in or stay out for further work.

When every difference is explained and either merged or rejected for later re-work or removal, the newly reconciled code is used as the new base for future development and refactoring. This does lose any comments that were in the code, but when this whole procedure has been necessary, the losing the comments hasn't been much of a loss to be frank.

The first time through, this can seem daunting, but members of my teams that have gotten good at this have found that on later projects, they can often seem the hero for being able to seemingly accomplish the impossible when a nasty situation arises, making it worthwhile to get this into your toolbox.

J Wynia
+1 for excellent detail, and a well-composed walk-through for a Reflection noob like me
JR MacDonald