Может ли сборка С#.dll содержать точку входа?

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

Я также хочу, чтобы он был единственным исполняемым в каталоге. Другими словами, я хочу, чтобы он запускал сборку .dll, а не сборку .exe. (Я могу потребовать, чтобы имя DLL файла, загружаемого в новый AppDomain, было одинаковым каждый раз, например Main.dll или что-то в этом роде.)

Было похоже, что AppDomain.ExecuteAssembly будет делать именно то, что я хотел. В нем говорится, что он начнет выполнение в "точке входа, указанной в заголовке .NET Framework".

Когда я пытаюсь использовать эту функцию, я получаю сообщение об ошибке "Точка входа не найдена в сборке" DllApp ".

У меня есть стартовая программа, просто пытающаяся запустить сборку:

static void Main()
{
    AppDomain domain = AppDomain.CreateDomain( "DllApp" );
    domain.ExecuteAssembly( "DllApp.dll" );
}

Код приложения в DLL файле с точкой входа по умолчанию:

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault( false );
        Application.Run( new Form1() );
    }
}

Эта страница в функциях Main() гласит, что "Библиотеки и службы не требуют метода Main как точки входа". Он не говорит, что они не могут иметь точку входа по умолчанию.

Я пробовал все различные перестановки public/private static void main, int return type, string [] args в качестве аргументов, с пространством имен, без пространства имен, статического/нестатического класса и т.д.

Мне удалось изменить свой код для наследования из MarshalByRefObject, а затем использовать CreateInstance для создания объекта, но похоже, что он будет более тесно соединяться стартером с программой, которую он должен начать. Если бы я мог использовать ExecuteAssembly, для запуска приложения просто понадобилось бы статическое void Main, и это действительно просто и сложно испортить.

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

Ответ 1

Вы можете скомпилировать .NET-приложение как exe (которое является сборкой) и переименовать его в .DLL, и оно будет работать как обычная сборка .NET.dll. Затем будет ваша точка входа.

Ответ 2

Я нашел совет, который не так прост. После некоторых экспериментов я пришел к успеху:

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

namespace FIT.DLLTest
{
  public class DLLTest
  {
    [STAThread]
    static void Main(string[] args)
    {
      int a = 1;
    }

    public DLLTest()
    {
      int b = 17;
    }

    public int Add(int int1, int int2)
    {
      return int1 + int2;
    }
  }
}

После компиляции я переименовал сгенерированный файл .exe в .DLL.

В материнской программе, использующей DLL, я сначала добавил DLLTest.dll в качестве ссылки, затем добавил код для выполнения DLL.

namespace TestDLLTest
{
  class TestDLLTest
  {
    static void Main(string[] args)
    {
      AppDomain domain = AppDomain.CreateDomain( "DLLTest" );
      domain.ExecuteAssembly( "DllTest.dll" );

      DLLTest dt = new DLLTest();
      int res2 = dt.Add(6, 8);
      int a = 1;
    }
  }
}

Viola Я могу выполнить и добавить точку останова в методе DLLTest.Main и увидеть, что я могу вызвать Main of DLLTest. Спасибо за обсуждение!

Ответ 3

Короткий ответ - нет. Файл .DLL представляет собой динамически связанную библиотеку, которая является кодом, вызываемым другой библиотекой. Я предполагаю, что Кейт сказал, что технически будет работать. Возможно, вы могли бы переименовать его в то, что когда-либо захотелось даже .txt или .pdf, до тех пор, пока вы запускаете приложение надлежащим образом. Главный вопрос, который у меня есть, Что ты пытаешься сделать?? Если вы не пытаетесь написать вредоносное ПО, почему вы хотите это сделать? Не то, чтобы я потворствовал написанию вредоносного ПО в плохих целях, но я знаю, что люди любят экспериментировать в своей собственной лаборатории, чтобы я не осуждал это. Если вы пишете вредоносное ПО, то что-то вроде С++, c или ассемблер может быть лучше, я думаю, С# мог бы выполнить эту работу, но meh...