If you like, you can skip the introduction and jump to Downloading .NET Reflector.
A brief history of .NET Reflector
In the beginning
In case you somehow missed it, .NET Reflector is a class browser, analyzer, and decompiler for .NET assemblies. Originally created by Lutz Roeder, it proved to be an extremely useful tool, making lists such as MSDN’s Ten Must-Have .NET Tools Every Developer Should Download Now. Best of all, .NET Reflector was released to the community for free, with Roeder developing and supporting the tool for over 8 years.
The downfall
However, in August 2008, Red Gate Software bought .NET Reflector. At the time, Roeder was told that Red Gate will continue to provide the free community version
. Red Gate themselves stated that The first thing we are doing is continuing to offer the software to the community for free downloading.
It didn’t stay that way. In February 2011, Red Gate announced that from version 7, .NET Reflector would no longer be free.
This might have been acceptable, but for the fact that free copies .NET Reflector expired after several months. Upon expiry, users were prompted to update to the latest version; if they declined, .NET Reflector would simply exit, although some versions contained a time-bomb that completely deleted .NET Reflector if it was too old. Effectively, all existing free users of .NET Reflector would be forced to either stop using .NET Reflector, or pay for version 7. The community backlash was immediate.
Scorched earth
After two months, Red Gate finally relented, partially reversing their decision to disable the free version of .NET Reflector. However, rather than once more releasing a free community edition, they instead only enabled existing free versions of .NET Reflector to update to a version that does not expire. For those users who had a self-deleting version, Red Gate offered no help. They also offered no way for new users to download the free version of .NET Reflector.
To date, Red Gate’s promise of maintaining a free community version remains broken. It has been more than a year since they first announced that they were going back on their word, but nothing has changed. While there are now more alternatives to .NET Reflector than ever, it is unfortunate that this whole situation came about in the first place.
A brief history of LookingGlass
Like most things developers create, LookingGlass was born out of curiosity. The question: Is it possible to download .NET Reflector from Red Gate without already having a copy? After all, old versions need a way to download updates somehow. Updating an old copy of .NET Reflector while running Wireshark quickly provided the answer: .NET Reflector makes two HTTP requests to Red Gate’s servers, the first to determine the URL of the update, and the second to actually download it.
LookingGlass is a small program that reproduces .NET Reflector’s requests to Red Gate’s servers and saves the result to a file. A few hacks were necessary to perfectly emulate how .NET Reflector makes its HTTP requests (See line 87), including not reusing the HTTP connection despite the Keep-Alive headers (.NET Reflector’s built-in updater launches as a separate process). From Red Gate’s side, it should be impossible to tell the difference between the two.
Downloading .NET Reflector
Simply save the below code as a file (For example, LookingGlass.cs), compile it and run the resulting program. It will save the downloaded file to the same directory as the program itself. If necessary, you can download Visual C# Express for free, or use the C# compiler (csc.exe) that is included with every version of the .NET framework to compile this code. LookingGlass should work perfectly on .NET 2.0 and above.
// This is free and unencumbered software released into the public domain. using System; using System.Diagnostics; using System.IO; using System.Net; using System.Reflection; namespace LookingGlass { class Program { static void Main(string[] args) { if (args.Length == 0) QueryDownloadUrl(@"http://reflector.red-gate.com/Reflector.version"); else Download(args[0]); } static void QueryDownloadUrl(string versionUrl) { Console.WriteLine("Phase 1: Getting download URL..."); HttpWebRequest request = GetHttpWebRequest(versionUrl); string downloadUrl = null; string data; using (WebResponse response = request.GetResponse()) { data = ReadResponse(response); foreach (string line in data.Split('\n')) { if (line.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { // If this version number stops working, search for other known .NET Reflector version numbers; Red Gate's own forums mention a few downloadUrl = line.Trim('\r').Replace("{Client}", "Reflector").Replace("{Version}", "6.1.0.11"); break; } } } if (downloadUrl == null) { Console.WriteLine("Failed to find download URL. Returned data was:"); Console.WriteLine(data); Console.ReadLine(); } else { Console.WriteLine("Launching download process..."); Process.Start(Process.GetCurrentProcess().MainModule.FileName, downloadUrl); Console.WriteLine("Phase 1 complete."); } } static void Download(string downloadUrl) { Console.WriteLine("Phase 2: Downloading..."); HttpWebRequest request = GetHttpWebRequest(downloadUrl); string path; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { path = GetDownloadFilename(response); if (response.StatusCode == HttpStatusCode.OK && !string.IsNullOrEmpty(path)) { Console.WriteLine("Saving to {0}...", path); SaveResponse(response, path); Console.WriteLine("Done!"); } else { Console.WriteLine("Download failed; server returned status code {0}. Returned data was:", response.StatusCode); Console.WriteLine(ReadResponse(response)); Console.ReadLine(); } } } static HttpWebRequest GetHttpWebRequest(string url) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Headers.Add("Cache-Control: no-cache, no-store, max-age=0"); // Emulate the manner in which the headers are handled FieldInfo usesProxySemantics = typeof(ServicePoint).GetField("m_ProxyServicePoint", BindingFlags.NonPublic | BindingFlags.Instance); usesProxySemantics.SetValue(request.ServicePoint, true); return request; } static string GetDownloadFilename(HttpWebResponse response) { string contentDisposition = response.Headers["content-disposition"]; if (string.IsNullOrEmpty(contentDisposition)) return null; string filenameField = "filename="; int index = contentDisposition.IndexOf(filenameField, StringComparison.CurrentCultureIgnoreCase); if (index < 0) return null; return contentDisposition.Substring(index + filenameField.Length).Trim('"'); } static string ReadResponse(WebResponse response) { using (Stream netStream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(netStream)) { return reader.ReadToEnd(); } } } static void SaveResponse(WebResponse response, string path) { byte[] buffer = new byte[4 * 1024]; int bytesRead; using (Stream netStream = response.GetResponseStream()) { if (File.Exists(path)) File.Delete(path); using (FileStream fileStream = File.Create(path)) { while ((bytesRead = netStream.Read(buffer, 0, buffer.Length)) > 0) { Console.Write("."); fileStream.Write(buffer, 0, bytesRead); } } } Console.WriteLine(); } } }
Where to from here?
Once you have .NET Reflector up and running, be sure to try out some of the many free community add-ins available on .NET Reflector’s site and Codeplex. Tell your friends about it. And above all, don’t always believe a company when they tell you they’ll keep a product free.
That’s a wonderful post, and a magnificent job you’ve done. You saved me a lot of time looking around for the last free version of Reflector.
Again, Well done and thanks for your sharing.
Fantastic! Worked perfectly.
Console was not visible at program termination, but in any case (after stepping to view results) stopped at “Phase 1 complete” with no download.
It won’t work in the debugger, because the end of Phase 1 launches a new process of the same executable with extra command line arguments.
If you specifically want to use the debugger, you’ll have to copy the value of the downloadUrl argument passed into Process.Start() on line 51 and set that in Project Properties > Debug > Command line arguments if you’re using Visual Studio. While you’re there, you should also probably set Working directory, as this is where the file will be downloaded to.
Sir,
please provide me a paypal link to le me buy you a beer!
Sir, you are a hero!
I was always sad regarding Red Gate’s desition. The Reflector .NET must be always a free tool for the .NET Community.
big thanks
you just made my day
Thanks guy. Helped big time!!
Awesome. Thanks x 1000!
Thanks. (And I haven’t even installed it yet :)
You have made lives around you better than any politician I have seen in my life.
Thank you!
Thank´s very good!
Thank you very much, it works.
Thanks a lot. This is awsome.
Great work! May god bless you.
When run the program crashes with an WebException: Proxy Authentication required. What does this mean? Has Red Gate blocked it?
It’s still working fine on my side. It sounds like you’re behind a proxy, possibly a corporate or university firewall. You will need to modify the proxy configuration in the code to suit your needs, but it will be probably be easier to run it at home or at an internet café.
First of all, nice work to get .Net Reflector!
There is an alternative, however, which is open source, does everything that .Net Reflector does and is free: http://ilspy.net/
Cheers!
БОЛЬШОЕ ПРИБОЛЬШОЕ СПАСИБО !!!!!
May the Force be with you!.. Thank You for striking down the greedy and the selfish ;)
It worked FLAWLESSLY!
You are the master.
Regards from Mexico.
Works like a charm.Thanks.
Mate…
You made my day!
Thanks a lot
These lines
FieldInfo usesProxySemantics = typeof(ServicePoint).GetField(“m_ProxyServicePoint”, BindingFlags.NonPublic | BindingFlags.Instance);
usesProxySemantics.SetValue(request.ServicePoint, true);
Don’t work in 4.0+compilers :/ usesProxySemantics is null.
I tried emulating this by setting the host to
request.Host = “reflector.red-gate.com:80”;
Anyway you could show me the headers those lines create?
To be specific, my code doesn’t work I get the 404 from redgate.
Also you don’t need to open a new process to make the request, http doesn’t send up any process information. FYI.
The original headers look like this:
At the time, setting m_ProxyServicePoint to true was the simplest way of getting .NET to output that Proxy-Connection header.
Pity it’s broken, but I suppose that’s what happens when one uses undocumented internals. ;)
I’ll take a look at updating it for newer versions of the .NET framework in the next few weeks.
True, except that if you don’t use a new process to make the second request, the first connection will be reused instead of being closed and a new one created. Spawning a new process is a simple way to fully emulate Reflector’s update process, including connection behaviour.
I found it on Mega.
But this method actualy works!
Awesome !
Thank you :)
Thanks! :) Great job.
Awesome man you are my hero…
This is simply great!
You are a star! Thanks for this. :)
Thank you very much, Nicely done, got it to work withing two minutes.
Thanks mate, but the problem is that, i can’t install add-ins.
Perhaps the specific add-ins you are trying to install are incompatible with the latest version of Reflector?
Hello! I’m having compiling and running it. I have a lot of errors. May be I will try again!
Check what version of .NET you are compiling for. This code requires .NET 2.0 and higher.
THANK YOU!!! you just helped me to become more knowledgeable about C# by providing a way to get this very valuable tools that allowed me to see how the compiler break codes apart.
Can it work now?
I tried it(build a program and run the program in an individual command window with admin), but I got the error “The remote server returned an error: (404) Not Found.” and time out. I am not sure if red gate do something or there is something wrong with my network.
It still works for me, so I would guess it’s your network or proxy. Perhaps try debugging it in Visual Studio Express?
You saved my day and in turn, my fist from (not) smashing it into the wall when I realized what Redgate conspired.
I get 404 error with version=6.1.0.11, any workarounds?
That’s weird, as it still works for me. At which step do you get the 404, 1 or 2?
hi, download failed every time so i used debugger to download.
Found exception at Line 64
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse());
The remote server returned an error: (404) Not Found.
Whats the solution.
I am on Windows 7 Enterprise
Visual Studio 2008
and i did follow your instructions in one of the above comments
“If you specifically want to use the debugger, you’ll have to copy the value of the downloadUrl argument passed into Process.Start() on line 51 and set that in Project Properties > Debug > Command line arguments if you’re using Visual Studio. While you’re there, you should also probably set Working directory, as this is where the file will be downloaded to.”
Please reply ASAP. Thanks.
What downloadUrl are you setting? Phase 1 gives me a downloadUrl of http://reflector.red-gate.com/ServeUpdates<GUID>.aspx?File=Reflector&Client=Reflector&Version=6.1.0.11
It is similar for me too… except for the GUID part obvivously :)
You are a genius!
Failed to get the file via a browser directly but I succeeded to get .NET reflector by running the program
Worked like a charm, but a couple of notes for people who might be having problems. I was not able to compile the code unless I was in admin mode (using the command line compiler) and I also had to run the program from the command line in admin mode to make it work.
Squid Can you pleases tell how to run it in admin mode?
Take a look at http://superuser.com/questions/42537/is-there-any-sudo-command-for-windows
Simply great !!
Thank you 1.000 times, worked perfectly.
Worked Great!!
Thanks!
It still works like a charm. Thanks a lot!
Anyway, in case if you guys haven’t noticed, ILSpy is the tool you should be using now. It has almost all the features of once free Reflector and is kept up-to-date by the community. Grab that here: http://ilspy.net/
Excellent – works a treat. Really saved my bacon today with a TFS server changeover and lost source code.
This still works fine. Just ran it now – but you forgot a rather important line of code. lol
After this line (52):
Process.Start(Process.GetCurrentProcess().MainModule.FileName, downloadUrl);
insert:
Download(downloadUrl);
And press F5 and reflector.exe is in my debug\bin folder containing version 6.
By the way, I have Windows 7, Visual Studio 2010, all Frameworks from 1.0 to 4.0. I created a new console application called LookingGlass, pasted this code, added Download(downloadUrl); on line 53 and ran it.
The downloaded zip file is 1.07MB.
Thank you for the valuable work Ashley, it is much appreciated. This version should have remained freely available as Roeder requested.
.NET Reflector’s updater launches as a separate process, which has the effect of opening a new socket to download the update. If the download is not launched in a separate process, the existing socket that requested the update URL is re-used, thanks to the Keep-Alive headers.
LookingGlass was designed to emulate the original updater’s behaviour as closely as possible, and that means re-launching itself with the download URL to prevent the existing socket from being re-used. This is also why the code won’t work when run from inside Visual Studio.
But I’m glad you got it working anyway. :)
I just ran this code to download .net reflector and amazingly worked for me. I have windows 7 (64-bit).
Thank you for the valuable posting. Really appreciate your good work.
THANK YOU!!!! LIFESAVER!!!
Thank you! Thank you! Thank you!!!
Incredible. Worked like a charm.
Thanks a lot
ILSpy is a bit lacking I believe.
When I created code using lambda expressions, ILSpy doesn’t display the compiler generated class; reflector does.
Hi Ashley..
Thank you so much!!! It worked like a charm :)
BIGGG THX !!! working very fine : 29 / 01 / 14
Brilliant Code! worked like a charm.
Thanks a lot.
Perfect execution!!!!!!!!!!!!
If it stops at Phase 1, just replace line 54 with this:
Download( downloadUrl );
I am receiving this exception. “The remote server returned an error: (407) Proxy Authentication Required.”
static void QueryDownloadUrl(string versionUrl)
{
Console.WriteLine(“Phase 1: Getting download URL…”);
HttpWebRequest request = GetHttpWebRequest(versionUrl);
string downloadUrl = null;
string data;
using (WebResponse response = request.GetResponse())
Your internet access seems to be via a proxy server, and it is that proxy that requires authentication. You with either have to modify the code to use the appropriate proxy settings, or you will need to use an unproxied internet connection.
Ah, yes that is the problem, Thanks,
First, thank you! This got me up and running again a long time ago. I recently upgraded to Windows 7 and had to dig this up and run it again to get Reflector back. Since then when browsing almost any of my own assemblies, I get an “Ambiguous match found.” error when I try to disassemble. It doesn’t happen for every member, but nearly every member. I’m bringing this here because only thing I can find online is saying to update to the latest version of Reflector. Any ideas what the problem might be?
Thanks for sharing the code. Works like a charm. Great job !!
Works great!
Hats off to you sir. Worked great. Great work. Many many Thanks a lot!!!.
Well done – nice work!
The code will actually work in debug if you change the Process.Start to read:
Process.Start(Assembly.GetExecutingAssembly().Location, downloadUrl);
cheers K.
Perfect! Been looking for quite some time! Mucho Gracias!
This article has been quite obsolete, but yet useful
You are an absolute champ! Thanks for sharing the code! :)
Now I can move forward in my learning
Have a good one!
Enter below URL in the Browser it will download the reflector version 6:
http://reflector.red-gate.com/DownloadUpdate?File=Reflector&Client=6&Version=4