Может ли сборка C# .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, аргументы string[] в качестве аргументов, с пространством имен, без пространства имен, статический/нестатический класс и т. д.

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

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


person Sean    schedule 06.03.2012    source источник
comment
Нет смысла иметь точку входа для сборки .NET (dll), так как она сама по себе не запускается как процесс.   -  person Zenwalker    schedule 06.03.2012


Ответы (3)


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

person Keith Nicholas    schedule 06.03.2012
comment
Это работало отлично, без необходимости что-либо менять. Интересно, почему я не подумал об этом... Спасибо, Кит. - person Sean; 08.03.2012

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

Я создал консольное приложение с простым main и включил остальную часть кода из моей оригинальной 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;
    }
  }
}

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

person user3324444    schedule 18.02.2014

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

person Four_0h_Three    schedule 06.03.2012
comment
Дело в том, что мой ответ заключается в том, что компилятор генерирует либо dll, либо exe, но оба являются сборками, его просто exes - это сборки с определенной точкой входа, о чем он просил. - person Keith Nicholas; 06.03.2012
comment
Нет, вредоносное ПО здесь не пишет. Я пытаюсь создать небольшую стартовую программу для теневого копирования моего основного приложения. Затем я могу легко обновить свое основное приложение без необходимости прыгать через другие обручи отдельных исполняемых файлов для обновления и т. д. Я просто хотел, чтобы стартер был полностью отделен, если это возможно, тогда я мог бы использовать его со всеми своими приложениями. - person Sean; 06.03.2012
comment
Если только вы не пытаетесь написать вредоносное ПО LOL!! - person Aditya Bokade; 25.08.2013
comment
«Обычные» dll win32 имеют точки входа для инициализации библиотеки, когда процесс присоединяется к ней, или финализации, когда все процессы выгружены. Это нормальная практика, поэтому обвинения во вредоносном ПО, имхо, неуместны. - person Pruyque; 06.09.2013