tags:

views:

641

answers:

6

Let's say I have a buggy application like this:

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("2 + 1 = {0}", Add(2, 1));
        }

        static int Add(int x, int y)
        {
            return x + x; // <-- oops!
        }
    }
}

The application is already compiled and deployed into the wild. Someone has found the bug, and now they are requesting a fix for it. While I could re-deploy this application with the fix, its an extreme hassle for reasons outside of my control -- I just want to write a patch for the bug instead.

Specifically, I want to insert my own MSIL into the offending assmembly source file. I've never done anything like this before, and googling hasn't turned up any useful information. If I could just see a sample of how to do this on the code above, it would help me out tremendously :)

How do I programmatically inject my own MSIL into a compiled .NET assembly?

[Edit to add:] To those who asked: I don't need runtime hotswapping. Its perfectly fine for me to have the app closed, manipulate the assembly, then restart the program again.

[Edit one more time:] It looks like the general consensus is "manipulating the assembly is a bad way to patch a program". I won't go down that road if its a bad idea.

I'll leave the question open because MSIL injection might still be useful for other purposes :)

+3  A: 

Rather than injecting MSIL at runtime, have you considered inserting the source directly into the assembly?

You can disassemble with ildasm, insert your MSIL, and then reassemble with ilasm, then deploy the product of that.

DannySmurf
This is the kind of solutions that people love to maintain.
erikkallen
-1: This would be impossible to maintain.
Jon Tackabury
And injecting MSIL into a running process is somehow easier?
DannySmurf
+1: how much maintenance is really necessary for one-time patches?
Juliet
You should never inject MSIL. Just rebuild and redeploy the new assembly. All this patching/disassembly is a maintenance nightmare.
Jon Tackabury
Perhaps, but that's not what the question was about.
DannySmurf
+3  A: 

I guess the question I would ask is "how would you deploy the patch"? Somewhere, you have to deploy something to fix a bug that is already out in the wild. Why would recompiling the dll and releasing the fixed version really be an issue? My guess is that figuring out how to programatically inject MSIL is going to be more trouble than simply redeploying a fixed assembly.

David Morton
This is how we do things now, and its a huge PITA. Some clients are using the old versions of the program, some of the DLLs are signed, some are very large, and all of them are version-tied to one another. I run into a lot of brickwalls, more than I can explain in this comment, by swapping out DLLs.
Juliet
If swapping DLLs is hard, how do you expect to inject code into them?
Jon Tackabury
I still don't understand why fixing the bug in the source code and recompiling only this assembly would be a problem? It goes without saying that you should not break interfaces and leave the version number unincremented.
0xA3
+2  A: 

If the reason you don't want to redeploy the whole stuff is because it is really half a gig, you should probably use some sort of binary patch tool - that's the first result on Google:

Binary Diff http://www.daemonology.net/bsdiff/

DrJokepu
+1  A: 

If your exe is signed then that wouldn't be possible. Why can't you just release that single assembly, instead of shipping the whole application again? It seems like you're aiming for a complex solution for a simple problem.

Jon Tackabury
A: 

You can use static MSIL Injection. Mono Cecil or PostSharp maybe helpful.

tobsen
A: 

good source of information...

IL Programming ebook

another is MS Press book on IL programming.

steps to decompile to IL and recompile

1. ildasm /output=ConsoleApplication1.il ConsoleApplication1.exe

2. //modify ConsoleApplication1.il code

3. ilasm ConsoleApplication1.il