Как внедрить код в вызовы метода C# из отдельного приложения
Мне было бы любопытно, если бы кто-нибудь знал о способе мониторинга информации времени выполнения приложения.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, но никогда не в C#.
РЕДАКТИРОВАТЬ: Чтобы уточнить, использование этого было бы добавить систему плагинов к игре на основе.Net, к которой у меня нет доступа к исходному коду.
9 ответов
Возможно, стоит изучить Mono.Cecil для внедрения кода. Он не будет работать в режиме онлайн, как вы описали в своем вопросе, но я полагаю, что он может делать то, что вы хотите в автономном режиме (иметь возможность найти данный метод, добавить код к нему и выписать измененную сборку). http://www.codeproject.com/KB/dotnet/MonoCecilChapter1.aspx
Вам нужно использовать Profiling API
сделать второй профиль программы первым. Затем вы получите уведомление о любых вызовах методов.
Что ж, сделать это без разрешения App1 сложно. Но при условии, что вы действительно хотите создать точку расширения в App1, довольно просто сделать то, что вы предлагаете, с помощью какой-то инфраструктуры расширяемости. Я предлагаю:
- Архитектура надстроек SharpDevelop
- Mono.Addins
- MS Managed Extensibility Framework
Так как я более знаком с 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 ... */
}
}
Другая идея - написать приложение, которое изменит исполняемый файл, который вы хотите отслеживать. Это сделало бы вещи, подобные тем, что делают инструменты профилирования, когда они "инструментируют" ваше приложение. По сути, вы используете отражение для просмотра приложения, затем воссоздаете исполняемый файл (с другим именем файла), используя функции Emit.NET, и одновременно вставляете свой код.
Конечно, если приложение попыталось сделать что-то безопасное, этой новой версии может быть запрещено взаимодействовать с другими его сборками.
С разъяснениями, которые вы сделали в комментарии, мне кажется, что вам было бы лучше разобрать и собрать, используя ildasm и ilasm.
В зависимости от того, как автор упаковал / структурировал свое приложение, вы можете добавить ссылку на его EXE-файл из вашего собственного проекта и просто выполнить его код из вашего собственного приложения. Если это работает, просто используйте Reflection, чтобы получить полезные интерфейсы / события / и т. Д., К которым вы можете подключиться (если они помечены как частные... в противном случае просто используйте их напрямую:). Вы можете добавить ссылку на любой EXE-файл, созданный с настройками по умолчанию для отладочных или выпусков, и использовать его как DLL.
Если это не сработает, есть продвинутые приемы, которые вы также можете использовать для обмена вызовами методов и тому подобное, но это выходит за рамки этого ответа... Я предлагаю сначала попробовать ссылку.
Вы можете попробовать CInject для внедрения вашего кода C# ИЛИ VB.NET в сборки
Впрыскивание кода в работающее приложение возможно. Это рабочий пример, но включает в себя внедрение в неуправляемую DLL.