Можно ли внедрить .NET dll в другое приложение .NET, возможно, с помощью app.config?

Я создал библиотеку классов .NET на С#, которая инициализирует некоторую регистрацию, отправляемую внешнему инструменту. Библиотека полностью отделена от любого приложения, но для ее инициализации мне нужно сделать для нее хотя бы один вызов метода.

Есть ли способ поместить что-то в app.config, которое будет автоматически загружать эту dll и что-то в ней вызывать? Я могу изменить содержимое в соответствии с чем угодно, мне не нужно поддерживать какое-либо собственное имя класса или имя метода или что-то еще.

Обратите внимание: мне нужно, чтобы это было сделано без каких-либо изменений в рассматриваемом приложении, за исключением изменения файла app.config.

Это возможно? Если да, то на что я должен смотреть?


person Lasse V. Karlsen    schedule 03.02.2010    source источник
comment
Назовите меня сумасшедшим, но почему ваш инструмент ведения журнала не инициализируется где-нибудь в статическом блоке инициализации?   -  person Noon Silk    schedule 04.02.2010
comment
Смысл в том, чтобы внедрить этот код в приложение, которое не было создано для его вызова. Статический конструктор вызывается только когда-то до использования кода в классе, нет никакой гарантии, что он когда-либо будет вызван, если вы на самом деле не используете класс. Поскольку приложение вообще не использует мою DLL-инъекцию, статический конструктор вызываться не будет.   -  person Lasse V. Karlsen    schedule 04.02.2010


Ответы (4)


Некоторое время я не мог понять, как это сделать. Первоначально я думал, что этого можно добиться, создав собственный веб-прокси, который настроит ведение журнала и загрузит его в основное приложение с помощью defaultProxy элемент конфигурации. Однако здесь возникает та же проблема, что и в других предложениях по конфигурации, заключающаяся в том, что код запускается только при необходимости (в данном случае при использовании HTTP-запроса), что требует внесения изменений в исходное приложение.

Однако я добился этого, изменив подход. Вместо того, чтобы пытаться заставить исходное приложение настроить ведение журнала, вы можете написать заглушку приложения, которое настраивает ведение журнала, а затем запускает исходное приложение.

Например:

У меня есть приложение WinForms под названием Forms.exe, точка входа которого определяется как:

[STAThread]
internal static void Main()
{
    Application.Run(new MainForm());
}

В моем приложении-заглушке (которое у меня есть как консольное приложение) я настраиваю ведение журнала, а затем загружаю и запускаю Forms.exe:

internal static void Main()
{
    ConfigureLogging()
    Assembly app = Assembly.LoadFrom(@".\Forms.exe");
    app.EntryPoint.Invoke(null, null);
}

При этом используется отражение для загрузки другого приложения в то, которое настраивает ведение журнала.

Предупреждения:

  • другое приложение должно быть приложением .Net, чтобы загружать его таким образом.
  • вам может понадобиться использовать Reflector для проверки другого приложения, чтобы определить правильные аргументы для передачи в точку входа (т.е. если он принимает string[] args, вам может потребоваться передать пустой string[] вместо null в качестве аргументов)
  • окно консоли исходного приложения будет зависать, пока работает другое приложение (это, вероятно, не проблема, но если это так, вы можете попытаться скрыть его, используя FreeConsole)
person adrianbanks    schedule 03.02.2010
comment
Ах, этот подход меня не осенил, да, это звучит гораздо более многообещающе. - person Lasse V. Karlsen; 04.02.2010
comment
Это, видимо, единственный оставшийся жизнеспособный вариант. Я не знаю точных правил, используемых для определения загрузки классов, связанных с ConfigurationSection, но кажется, что они загружаются только в том случае, если я когда-либо касаюсь этой конфигурации. В моем случае, как и в общем случае, приложение не читает эту конфигурацию, так что работать не будет. Тем не менее, проект приложения-заглушки работает как шарм. - person Lasse V. Karlsen; 06.02.2010

Вероятно, это будет считаться взломом, но если вы поставите что-то, что наследует ConfigurationSection в вашей dll и добавьте этот раздел конфигурации в ваш app.config, это позволит вам выполнять код в конструкторе раздела конфигурации и, таким образом, делать то, что вы хотите. Конечно, он будет вызываться только один раз, при запуске приложения, но, если я правильно понял, этого будет достаточно.

person Klaus Byskov Pedersen    schedule 03.02.2010
comment
Я попробую это, звучит многообещающе. - person Lasse V. Karlsen; 03.02.2010
comment
Взлом в порядке. Эта dll подключается к системе прослушивания Debug и Trace для захвата всех сообщений журнала и запускает фоновые потоки для мониторинга использования памяти и процессора, все отправляется во внешнее приложение регистратора. Это инструмент судебной отладки, который мне нужно использовать для приложения, которое я, к сожалению, не могу изменить. - person Lasse V. Karlsen; 03.02.2010
comment
Ну, тогда я не понимаю, почему это не сработает. Удачи с этим и дайте мне знать, как это получается. - person Klaus Byskov Pedersen; 03.02.2010
comment
@Lasse: Если это инструмент судебной отладки, рассматривали ли вы возможность использования доступных вам крючков профилировщика / отладчика CLR? - person Brian Genisio; 03.02.2010
comment
Нет, не пробовал, как это будет работать, легко ли будет настроить? Сейчас я пробую совет раздела конфигурации, но, похоже, он вообще не загружает класс раздела. Я посмотрю на это еще немного, прежде чем изменить свой вопрос или оставить еще один комментарий. @ Брайан, не могли бы вы оставить здесь ответ с некоторой информацией об этом для меня? - person Lasse V. Karlsen; 03.02.2010
comment
@Lasse, да, я тоже пытаюсь, но с тем же результатом, что и ты. На самом деле я был почти уверен, что он загрузит разделы, но похоже, что я могу ошибаться. Может быть, вы захотите изучить комментарий Брайана немного подробнее. - person Klaus Byskov Pedersen; 03.02.2010
comment
@Lasse: я никогда не использовал API профилирования в .net, но это то, что используют все отладчики и профилировщики для выполнения своей работы (Ants, .Trace, .Net Memory Profiler и т. д.) - person Brian Genisio; 05.02.2010

Snoop делает это с помощью вуду C++. К счастью, исходники доступны — посмотрите в проекте под названием «ManagedInjector».

person Rob Fonseca-Ensor    schedule 03.02.2010

Да, вы можете использовать отражение для загрузки содержимого сборки

person Anton Setiawan    schedule 03.02.2010
comment
Весь смысл был в том, чтобы вообще не изменять код целевого приложения. Я могу легко добавить отражение или что-то еще, если я хочу пойти по этому пути. - person Lasse V. Karlsen; 03.02.2010
comment
@Lasse: Хмммм ... Если целевое приложение не было создано для этого, и вы не хотите его обновлять, вы застряли. Это было бы проблемой безопасности, если бы это было так волшебно. - person Brian Genisio; 03.02.2010
comment
Да, это тоже мое предположение, и, поскольку я не могу заставить ответ раздела конфигурации работать, я предполагаю, что мне все-таки нужен какой-то код в приложении. Возможно, вместо этого сработает отладочный крючок, который @Brian прокомментировал выше. - person Lasse V. Karlsen; 03.02.2010