How to Inject code in c# method calls from a separate app

10.2k Views Asked by At

I was curious if anyone knew of a way of monitoring a .Net application's runtime info (what method is being called and such)

and injecting extra code to be run on certain methods from a separate running process.

say i have two applications:

app1.exe that for simplicity's sake could be

class Program
{
    static void Main(string[] args)
    {
      while(true){
        Somefunc();
      }
    }

    static void Somefunc()
    {
       Console.WriteLine("Hello World");
    }
} 

and I have a second application that I wish to be able to detect when Somefunc() from application 1 is running and inject its own code,

 class Program
 {
     static void Main(string[] args)
     {
       while(true){
          if(App1.SomeFuncIsCalled)
             InjectCode();
         }
     }

    static void InjectCode()
    {
       App1.Console.WriteLine("Hello World Injected");
    }
 } 

So The result would be Application one would show

Hello World
Hello World Injected 

I understand its not going to be this simple ( By a long shot ) but I have no idea if it's even possible and if it is where to even start.

Any suggestions ?

I've seen similar done in java, But never in c#.

EDIT: To clarify, the usage of this would be to add a plugin system to a .Net based game that I do not have access to the source code of.

9

There are 9 best solutions below

0
genki On BEST ANSWER

It might be worth looking into Mono.Cecil for code injection. It won't work online the way you described in your question, but I believe it may do what you want offline (be able to find a given method, add code to it, and write out the modified assembly). http://www.codeproject.com/KB/dotnet/MonoCecilChapter1.aspx

1
Barry Kelly On

With the clarifications you made in a comment, it seems to me you would be better off disassembling and reassembling using ildasm and ilasm.

1
SLaks On

You need to use the Profiling API to make the second program profile the first one. You can then be notified of any method calls.

3
Scott Whitlock On

Well, to do that without App1's permission is difficult. But assuming you actually want to create an extension point in App1, it's relatively straightforward to do what you're suggesting with some kind of extensibility framework. I suggest:

Since I am more familiar with MEF, here's how it would look:

class Program
{
    [ImportMany("AddinContractName", typeof(IRunMe))]
    public IEnumerable<IRunMe> ThingsToRun { get; set; }

    void SomeFunc()
    {
        foreach(IRunMe thing in ThingsToRun)
        {
            thing.Run();
        }
        /* do whatever else ... */
    }
}
2
John Fisher On

Another idea is to write an app that will change the exe you want to monitor. It would do things similar to what profiling tools do when they "instrument" your app. Basically, you use reflection to browse the app, then you re-create the exe (with a different file name) using the Emit features of .NET and insert your code at the same time.

Of course, if the app attempted to do things securely, this new version may not be allowed to communicate with its other assemblies.

0
AudioBubble On

Depending on how the author packaged/structured his application, you might be able to add a reference to his EXE file from your own project and just execute his code from within your own application. If that works, it's just a matter of using Reflection at that point to get at useful interfaces/events/etc that you can plug into (if they are marked private...otherwise just use them directly :). You can add a reference to any EXE built with the default settings for debug or release builds, and use it just like a DLL.

If that doesn't work there are advanced tricks you can use as well to swap out method calls and such, but that is beyond the scope of this reply...I suggest trying the reference thing first.

0
Brian On

Injecting code into a running app is possible. This is a working example, but involves injection into an unmanaged dll.

0
Nicolas Dorier On

Inject code in the assembly with Mono Cecil

0
GeekzSG On

You can try out CInject to inject your C# OR VB.NET code into assemblies