0

В одной папке имеется eкзешник и zedgraph.dll, но если я удаляю из папки zedgraph.dll то eкзешник не запускается. Как эту проблему решить. Надо чтобы программа запускалась без этой библиотеки. Можно ее как то включить в ексешник?

Pavel Mayorov
  • 58,537
SVD102
  • 953
  • 7
    Решение простое: не удалять DLL, так как она является необходимой для работы приложения. – Владимир Мартьянов Mar 02 '16 at 10:40
  • @Владимир Мартьянов Как я не додумался... – SVD102 Mar 02 '16 at 10:48
  • 1
    Какую проблему вы на самом деле хотите решить? – Nofate Mar 02 '16 at 10:54
  • 1
    DLL не предназначена для статической линковки, потому что это динамическая библиотека. – Владимир Мартьянов Mar 02 '16 at 10:58
  • Надо чтоб программа запускалась с одного ексешника. Разве нельзя включить эту библиотеку в сборку(если я правильно выразился) перед релизом. – SVD102 Mar 02 '16 at 11:06
  • @SVD102 "DLL не предназначена для статической линковки" вам уже написали. Смотрите в сторону статической линковки, хотя есть подозрение что в .NET вы с этим и напляшитесь и налюбитесь... – Владимир Мартьянов Mar 02 '16 at 11:07
  • 1
    @ВладимирМартьянов тут не подозрение, а утверждение. Это как пытаться запустить .NET приложение без .NET. Просто родные .NET DLL лежат не в в папке проекта а в GAC и на Win Vista+ в каком-то варианте установлены по умолчанию, поэтому появляется иллюзия что их нет. Но это всего лишь иллюзия – rdorn Mar 02 '16 at 11:18
  • @rdorn ну я ни разу не спец по .NET, к счастью. Вот и всего лишь подозреваю. – Владимир Мартьянов Mar 02 '16 at 11:27
  • @ВладимирМартьянов дык я ж не обвиняю, просто сообщаю =) – rdorn Mar 02 '16 at 11:32
  • А как тогда эту библиотеку добавить к "родным" библиотекам. – SVD102 Mar 02 '16 at 11:33
  • Так на вскидку не помню, да и зачем? Это придется делать на каждой машине, где вы захотите запустить ваше приложение, что пожалуй только добавит "радости" пользователям. Лучше посмотрите в сторону публикации приложения ClickOnce, или запакуйте релиз в zip и отдавайте на скачивание архивом. – rdorn Mar 02 '16 at 11:36
  • если очень хочется запихнуть сборку в GAC, почитайте тут https://msdn.microsoft.com/ru-ru/library/ex0ss12c(v=vs.110).aspx – rdorn Mar 02 '16 at 11:39
  • Мне и надо добавить радости человеку который будет ей пользоваться на производстве) – SVD102 Mar 02 '16 at 11:46
  • 4
    Ну и вынесите этому вашему пользователю ярлык запуска приложения на рабочий стол. Тогда ему вообще будет не интересно где расположен исполняемый файл и какие там рядом с ним ещё библиотеки. – aleks.andr Mar 02 '16 at 11:59
  • @rdorn А можно из обычной консоли добавить dll файл к родительским? – SVD102 Mar 03 '16 at 06:03

2 Answers2

6

Как это делаю я:

  1. Добавляю сборку как обычный файл явно в проект.

  2. Указываю сборке (пкм по ней, свойства) Build Action - Embedded Resource, Do not copy.

  3. На запуске приложения подписываюсь на событие резолва сборок

    AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly.ResolveInternalAssembly;
    
    internal static Assembly ResolveInternalAssembly(object sender, ResolveEventArgs args)
    {
      var resource = args.Name;
      var resourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
      if (!resourceNames.Any())
        return null;
    
      if (resource.Contains(','))
        resource = resource.Substring(0, resource.IndexOf(','));
    
      var assemblyFile = string.Format(".{0}.dll", resource);
      var resourceName = resourceNames.SingleOrDefault(s => s.EndsWith(assemblyFile));
      if (string.IsNullOrWhiteSpace(resourceName))
      {
        assemblyFile = assemblyFile.Remove(0, 1);
        resourceName = resourceNames.SingleOrDefault(s => s.EndsWith(assemblyFile));
      }
    
      if (string.IsNullOrWhiteSpace(resourceName))
        return null;
    
      using (var stream = assembly.GetManifestResourceStream(resourceName))
      {
        var block = new byte[stream.Length];
        stream.Read(block, 0, block.Length);
        return Assembly.Load(block);
      }
    }
    
Monk
  • 4,478
  • интересный вариант, а в чем плюсы и минусы? не для поспорить, просто интересно. – rdorn Mar 02 '16 at 16:46
  • @rdorn все либы внутри, простая такая portable программа. – Monk Mar 02 '16 at 17:22
  • а на время запуска не сказывается? – rdorn Mar 02 '16 at 17:38
  • Когда какой то nhibernate запускается секунды 3, доступ к либам не ощутим, например. – Monk Mar 02 '16 at 17:52
  • ок, спасибо, еще один прием в копилку. – rdorn Mar 02 '16 at 17:53
  • Немного по теме: http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57143.aspx – VladD Mar 03 '16 at 18:15
4

Есть утилиты, которые собирают ехе-шник с несколькими библиотеками в один - это ILMerge, libz

kvvk
  • 675
  • Это не пойдёт, если библиотека нативная. А так вообще хороший вариант. – VladD Mar 03 '16 at 13:40
  • @VladD да, конечно. по чесноку, мне больше нравится решение с EmbeddedResource – kvvk Mar 03 '16 at 13:54
  • @VladD, а как осуществляется поиск нативных библиотек? Мое решение подозреваю тоже для них не сработает, т.к. они не вызывают событие, видимо. – Monk Mar 03 '16 at 15:23
  • @kvvk: У решения с AssemblyResolve та же проблема, в общем-то. Загрузка нативных библиотек не настолько гибкая. (Хотя, возможно, есть WinAPI'шные хуки.) – VladD Mar 03 '16 at 17:39
  • @Monk: Угу, это только для .NET-сборок. – VladD Mar 03 '16 at 17:40
  • @Monk: Алгоритм поиска нативных библиотек как в нативных приложениях: текущий каталог, каталог приложения, %PATH%, C:\Windows, known dlls и т. д. – VladD Mar 03 '16 at 18:18