Как внедрить код в вызовы методов С# из отдельного приложения

Мне было любопытно, знает ли кто-нибудь о способе мониторинга информации о времени выполнения приложения .Net (какой метод вызывается и тому подобное)

и внедрение дополнительного кода для запуска определенных методов из отдельного запущенного процесса.

скажем, у меня есть два приложения:

app1.exe, который для простоты может быть

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

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

и у меня есть второе приложение, которое я хочу иметь возможность обнаруживать, когда работает Somefunc() из приложения 1, и вводить свой собственный код,

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

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

Таким образом, результатом будет приложение, которое можно было бы показать

Hello World
Hello World Injected 

Я понимаю, что это будет не так просто (наверное), но я понятия не имею, возможно ли это вообще, и есть ли с чего начать.

Какие-либо предложения ?

Я видел подобное в Java, но никогда в С#.

РЕДАКТИРОВАТЬ: Чтобы уточнить, использование этого будет заключаться в добавлении системы плагинов в игру на основе .Net, к исходному коду которой у меня нет доступа.


person Fusspawn    schedule 22.07.2009    source источник


Ответы (9)


Возможно, стоит изучить Mono.Cecil для внедрения кода. Он не будет работать в сети так, как вы описали в своем вопросе, но я считаю, что он может делать то, что вы хотите, в автономном режиме (иметь возможность найти заданный метод, добавить к нему код и записать модифицированную сборку). http://www.codeproject.com/KB/dotnet/MonoCecilChapter1.aspx

person genki    schedule 22.07.2009

Что ж, сделать это без разрешения App1 сложно. Но предполагая, что вы действительно хотите создать точку расширения в App1, относительно просто сделать то, что вы предлагаете, с какой-либо инфраструктурой расширяемости. Я предлагаю:

Поскольку я больше знаком с MEF, вот как это будет выглядеть:

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

    void SomeFunc()
    {
        foreach(IRunMe thing in ThingsToRun)
        {
            thing.Run();
        }
        /* do whatever else ... */
    }
}
person Scott Whitlock    schedule 22.07.2009
comment
Хотя я знаю, что это немного морально неправильно, позвольте мне объяснить, для чего он предназначен, мне нравится играть в небольшую одиночную игру, в которой нет какой-либо поддержки дополнений (игра также основана на .net), но есть несколько пользовательских аддонов, которые я хотел бы сделать для своей собственной версии Невозможно получить доступ к коду/или отсутствию системы аддонов, я намеревался сделать свой собственный, у меня нет намерений или публиковать это для публики, - person Fusspawn; 22.07.2009
comment
@Fusspawn - понятно. Сначала я не был уверен, есть ли у вас доступ к коду приложения 1 или нет. Я вижу, вы отредактировали свой вопрос, чтобы уточнить. Спасибо. - person Scott Whitlock; 22.07.2009
comment
В любом случае, спасибо за ваш ответ. Я никогда не знал, что это существует в С#, и я добавил его в свой список для чтения :) - person Fusspawn; 22.07.2009

Вам нужно использовать Profiling API, чтобы сделать второй профиль программы первым один. Затем вы можете получать уведомления о любых вызовах методов.

person SLaks    schedule 22.07.2009
comment
Это не поможет с модификацией, хотя. - person Barry Kelly; 22.07.2009

Другая идея состоит в том, чтобы написать приложение, которое изменит исполняемый файл, который вы хотите отслеживать. Это будет делать вещи, похожие на то, что делают инструменты профилирования, когда они «инструментируют» ваше приложение. По сути, вы используете отражение для просмотра приложения, затем повторно создаете исполняемый файл (с другим именем файла), используя функции Emit .NET, и одновременно вставляете свой код.

Конечно, если приложение попыталось сделать что-то безопасно, этой новой версии может быть запрещено взаимодействовать с другими его сборками.

person John Fisher    schedule 22.07.2009
comment
Это я надеялся сделать, запустив фоновое приложение и сделав это в режиме реального времени, или так, как вы предложили, я просто не знал, как это сделать. - person Fusspawn; 22.07.2009
comment
Вы также можете поискать некоторые инструменты аспектно-ориентированного программирования, поскольку некоторые из них используют тот же принцип изменения уже существующей сборки. - person John Fisher; 22.07.2009

С разъяснениями, которые вы сделали в комментарии, мне кажется, вам лучше разобрать и собрать заново, используя ildasm и ilasm.

person Barry Kelly    schedule 22.07.2009
comment
Я думаю, что ты прав. Я надеялся, что до этого не дойдет. - person Fusspawn; 22.07.2009

В зависимости от того, как автор упаковал/структурировал свое приложение, вы можете добавить ссылку на его EXE-файл из своего собственного проекта и просто выполнить его код из своего собственного приложения. Если это сработает, в этот момент нужно просто использовать Reflection, чтобы получить полезные интерфейсы/события/и т. д., к которым вы можете подключиться (если они помечены как частные... в противном случае просто используйте их напрямую :). Вы можете добавить ссылку на любой EXE-файл, созданный с настройками по умолчанию для отладки или сборки выпуска, и использовать его так же, как DLL.

Если это не сработает, есть продвинутые приемы, которые вы также можете использовать для замены вызовов методов и тому подобного, но это выходит за рамки этого ответа... Я предлагаю сначала попробовать справочную вещь.

person Community    schedule 22.07.2009

Внедрение кода в работающее приложение возможно. Это — рабочий пример, но включает внедрение в неуправляемую dll.

person Brian    schedule 22.07.2009

Вставка кода в сборку с помощью Mono Cecil

person Nicolas Dorier    schedule 22.07.2009

Вы можете попробовать CInject для внедрения кода C# ИЛИ VB.NET в сборки.

person GeekzSG    schedule 03.09.2012