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