Как найти файлы зависимостей для dll



иногда, когда я делаю небольшой проект, я недостаточно осторожен и случайно добавляю зависимость для DLL, о которой я не знаю. Когда я отправляю эту программу другу или другим людям, «это не работает», потому что «некоторые DLL» отсутствуют. Это, конечно, потому что программа может найти DLL на моей системе, но не на их.

есть ли программа / скрипт, который может сканировать исполняемый файл для зависимостей DLL или выполнять программу в «чистой» среде без DLL для тестирования предотвратите эти упс ситуациях?


806  


10  

10 ответов:

dumpbin из Visual Studio tools (VCbin папка) может помочь здесь:

dumpbin /dependents your_dll_file.dll

Я могу порекомендовать интересное решение для поклонников Linux. После того, как я изучил это решение, я переключился с DependencyWalker на это.

вы можете использовать ваш любимый ldd по сравнению с Windows, связанные с exe,dll.

для этого Вам необходимо установить программа (базовая установка, без каких-либо дополнительных пакетов не требуется) на вашем Windows, а затем просто запустите Cygwin Terminal. Теперь вы можете запускать свои любимые команды Linux, в том числе:

$ ldd your_dll_file.dll

UPD: можно использовать ldd и через Git Bash terminal на Windows. Нет необходимости устанавливать cygwin в случае, если у вас уже установлен git.

  1. есть программа под названием «зависимость»
  2. Если у вас установлен cygwin, ничего проще, чем файл ldd.exe

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

проблемы Dll имеют разные лица. Если вы используете Visual Studio и динамически подключаетесь к CRT, вам нужно распространять библиотеки DLL CRT. Обновите свой VS, и вам придется распространять другую версию CRT. Просто проверка зависимостей не достаточно, так как вы можете пропустить их. Выполнение полной установки на чистую машину является единственным безопасным решением, IMO.

Если вы не хотите устанавливать полномасштабную тестовую среду и иметь Windows 7, Вы можете использовать XP-Mode в качестве начальной чистой машины и XP-более для дублирования виртуальной машины.

на вашей машине разработки вы можете выполнить программу и запустить Sysinternals Process Explorer. В нижней панели он покажет вам загруженные DLL и текущие пути к ним, что удобно по ряду причин. Если вы выполняете свой пакет развертывания, он покажет, на какие библиотеки DLL ссылаются в неправильном пути (т. е. не были упакованы правильно).

В настоящее время наша компания использует проекты установщика Visual Studio для обхода дерева зависимостей и вывод в виде свободных файлов программы. В VS2013, это теперь расширение:https://visualstudiogallery.msdn.microsoft.com/9abe329c-9bba-44a1-be59-0fbf6151054d. затем мы упаковываем эти свободные файлы в более полный установщик, но, по крайней мере, эта установка проецирует все зависимости dot net и отбрасывает их в одно место и предупреждает вас, когда что-то отсутствует.

пожалуйста, поиск «зависит.exe » в google, это крошечная утилита для обработки этого.

Если у вас есть исходный код, вы можете использовать ndepend.

http://www.ndepend.com/

Это дорого и делает намного больше, чем анализ зависимостей, поэтому это может быть излишним для того, что вы ищете.

NDepend уже упоминался Джесси (если вы анализируете .NET-код), но давайте объясним, как именно это может помочь.

есть ли программа/скрипт, который может сканировать исполняемый файл для DLL
зависимости или выполнение программы в «чистой» среде без DLL
для тестирования, чтобы предотвратить эти ситуации упс?

на панели свойств проекта NDepend можно определить, какие сборки приложения следует анализировать (зеленым цветом) и вопросом, что происходит предположит Сторонние сборки, используемые приложениями (в синем). Список каталогов, в которых выполняется поиск приложений и сторонних сборок.

NDepend Project Properties Application and Third-Party assemblies

если сторонняя сборка не найдена в этих каталогах, она будет находиться в режиме ошибки. Например, если я удалю каталог .NET Fx C:WINDOWSMicrosoft.NETFrameworkv4.0.30319 Я вижу, что .NET Fx сторонних сборок нет решено:

NDepend Project Properties Application and Third-Party assemblies not resolved

отказ от ответственности: я работаю на NDepend

I have a collection of DLLs(say 20). How do I find out all the DLLs on which one specific DLL (say DLL A) is depending upon?

kayleeFrye_onDeck's user avatar

asked Feb 27, 2013 at 13:30

Abhijeet's user avatar

If you mean programmatically, use Assembly.GetReferencedAssemblies.

You can use that recursively to find all the assemblies you need. (So you find the dependencies of X, then the dependencies of the dependencies, etc.)

answered Feb 27, 2013 at 13:32

Jon Skeet's user avatar

Jon SkeetJon Skeet

1.4m859 gold badges9096 silver badges9169 bronze badges

8

Since the question is tagged «C#», I would assume you are talking about managed dlls (assemblies). In that case, dependencywalker is not useful. If you want to do that with a program, good ones are dotPeek by JetBrians and Reflector by RedGate. Or you can even use the object inspector in Visual Studio.

However, it can be a long process and cumbersome too. I would write a short C# program/F# script that uses Assembly.GetReferencedAssemblies, as Jon mentioned.

If instead you want to examine native DLLs dependencies with a program (C# code), you have to walk the examine the PE file (the MS dll and exe file format) and its IAT (import address table). Not easy, but not impossible…

I would start here on MSDN and here to understand PE sections, and use a managed library to read it (there are many, including some from the Mono project (I’m thinking of Cecil, it should work with native binaries too); in the past I have used this one from the good John Gough.

answered Feb 27, 2013 at 13:40

Lorenzo Dematté's user avatar

Lorenzo DemattéLorenzo Dematté

7,5583 gold badges36 silver badges76 bronze badges

All answer credit goes to previous authors for the usage of Assembly.GetReferencedAssemblies. This is just a write-and-forget C# console app that works solely for .NET assemblies. return 0 on assemblies you were able to check, and when successful, outputs them to STDOUT. Everything else will return 1 and print some kind of error output. You can grab the gist here.

using System;
using System.Reflection;
using System.IO;
namespace DotNetInspectorGadget
{
    class DotNetInspectorGadget 
    {
        static int Main(string[] args) 
        {
          if(args.GetLength(0) < 1)
          {
            Console.WriteLine("Add a single parameter that is your" +
            " path to the file you want inspected.");
            return 1;
          }
          try {
                var assemblies = Assembly.LoadFile(@args[0]).GetReferencedAssemblies();

                if (assemblies.GetLength(0) > 0)
                {
                  foreach (var assembly in assemblies)
                  {
                    Console.WriteLine(assembly);
                  }
                  return 0;
                }
          }
          catch(Exception e) {
            Console.WriteLine("An exception occurred: {0}", e.Message);
            return 1;
          } finally{}

            return 1;
        }
    }
}

Usage:

call %cd%dotnet_inspector_gadget.exe C:WindowsMicrosoft.NETassemblyGAC_64Microsoft.ConfigCI.Commandsv4.0_10.0.0.0__31bf3856ad364e35Microsoft.ConfigCI.Commands.dll

Output:

mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

answered Apr 27, 2017 at 23:45

kayleeFrye_onDeck's user avatar

You can use dependency walker http://www.dependencywalker.com to figure this out. Take note on the difference between x32 and x64 though.

Dependency Walker is a free utility that scans any 32-bit or 64-bit
Windows module (exe, dll, ocx, sys, etc.) and builds a hierarchical
tree diagram of all dependent modules.

Alex's user avatar

Alex

7,8481 gold badge41 silver badges56 bronze badges

answered Feb 27, 2013 at 13:31

Aniket Inge's user avatar

Aniket IngeAniket Inge

25.3k5 gold badges50 silver badges78 bronze badges

1

For .NET assemblies, a terrific tool to view the assemblies an assembly is dependent on is AsmSpy.

answered Feb 10, 2015 at 14:19

Alexander van Trijffel's user avatar

1

If you want the DLL’s (the files) then, Assembly.GetReferencedAssemblies will also return the .Net Framework assemblies.

Here is a simple code snippet that will get the dll’s it can find in the current directory (and also include some other related files):

private readonly string[] _extensions = { ".dll", ".exe", ".pdb", ".dll.config", ".exe.config" };

private string[] GetDependentFiles(Assembly assembly)
{
    AssemblyName[] asm = assembly.GetReferencedAssemblies();
    List<string> paths = new List<string>(asm.Length);
    for (int t = asm.Length - 1; t >= 0; t--)
    {
        for (int e = _extensions.Length - 1; e >= 0; e--)
        {
            string path = Path.GetFullPath(asm[t].Name + _extensions[e]);
            if (File.Exists(path)) paths.Add(path);
        }
    }

    return paths.ToArray();
}

You can call it like so: MessageBox.Show(string.Join("rn", GetDependentFiles(Assembly.GetEntryAssembly())));

answered Apr 18, 2018 at 13:24

Louis Somers's user avatar

Louis SomersLouis Somers

2,5003 gold badges26 silver badges57 bronze badges

This example shows a situation where we also want to display recursive dependencies. Tested with .net 4.5.2


using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows.Forms;

var assemblyPath = @"C:TempSome-Assembly.dll";
var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
var indent = 0;
PrintDependencies(assembly.GetReferencedAssemblies(), ref indent, new List<string>());

private void PrintDependencies(
    IEnumerable<AssemblyName> names, 
    ref int indent, 
    ICollection<string> visited)
{
    indent++;
    foreach (var name in names)
    {
        Print(name, indent);
        if (visited.Contains(name.FullName)) continue;
        visited.Add(name.FullName);
        var assembly = Assembly.ReflectionOnlyLoad(name.FullName);
        PrintDependencies(assembly.GetReferencedAssemblies(), ref indent, visited);
    }
    indent--;
}

// Rich text box was used, but can be anything else
private void Print(AssemblyName name, int indent) 
    => richTextBox.AppendText($"{new string('-', indent * 4)}{name.FullName}{Environment.NewLine}");

enter image description here

answered Mar 25 at 18:45

Daniel Dušek's user avatar

Daniel DušekDaniel Dušek

13.6k5 gold badges35 silver badges51 bronze badges

Начало тут:
1. динамически подключаемые библиотеки;
2. о динамически подключаемых библиотеках подробнее;
3. преимущества динамического связывания;
4. создание динамически подключаемой библиотеки;
5. функция точки входа DLL;
6. динамическое связывание во время запуска;
7. динамическое связывание во время выполнения.

Перевод с английского статьи от 31.05.2018 г. «Dynamic-Link Library Search Order»:
https://docs.microsoft.com/ru-ru/windows/win32/dlls/dynamic-link-library-search-order
(На данный момент на этом сайте нет перевода этой статьи на русский, есть только версия на английском.)

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

Так как статья довольно длинная [и в ней много повторов, поэтому она довольно нудная], то вот ее содержание со ссылками на ее разделы (все они находятся на этой же странице):

  • факторы, влияющие на процесс поиска;
  • порядок поиска DLL для приложений «Windows Store»:
    • стандартный порядок поиска DLL для приложений «Windows Store»;
    • альтернативный порядок поиска DLL для приложений «Windows Store»;
  • порядок поиска DLL для приложений настольного компьютера:
    • стандартный порядок поиска DLL для приложений настольного компьютера;
    • альтернативный порядок поиска DLL для приложений настольного компьютера;
    • порядок поиска DLL с использованием флагов LOAD_LIBRARY_SEARCH.

Факторы, влияющие на процесс поиска

Следующие факторы влияют на то, будет ли система искать DLL:

  • если DLL с тем же самым именем модуля уже загружена в память, система проверит только [следует ли выполнить] перенаправление [перенаправление включается наличием в папке с исполняемым файлом приложения пустого файла с таким же именем, как у приложения, и расширением .local и указывает системе начать поиск DLL с папки, в которой находится этот файл .local] и манифест [на наличие указаний о местонахождении нужной DLL] и [при отсутствии перенаправления и манифеста] будет считать результатом поиска загруженную DLL, при этом не будет иметь значения, в каком каталоге эта загруженная DLL находится. Система не станет выполнять других действий по поиску DLL;
  • если DLL есть в списке библиотек DLL, известных той версии операционной системы Windows, в которой запущено приложение, система использует свою копию известной DLL (и свои копии библиотек DLL, от которых эта известная DLL зависит, если таковые имеются) вместо того, чтобы искать эту DLL. Увидеть список известных текущей системе DLL можно, обратившись к следующему ключу реестра: HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerKnownDLLs;
  • если DLL имеет зависимости [от других DLL], система будет искать библиотеки DLL, от которых зависит исходная, так, как если бы эти библиотеки загружались с указанием только имен их модулей. Это правило остается верным, даже если исходная DLL загружалась с указанием полного пути к ней.

Порядок поиска DLL для приложений «Windows Store»

Когда приложение «Windows Store» загружает упакованный модуль [DLL] посредством вызова функции LoadPackagedLibrary, DLL должна находиться в графе зависимостей пакета для процесса. Подробнее об этом читайте в описании функции LoadPackagedLibrary. Когда приложение «Windows Store» загружает модуль [DLL] другими средствами и не указывает полный путь к нему, система ищет DLL и ее зависимости [модули, от которых эта DLL зависит] во время запуска программы так, как описано в этом разделе.

Замечание для пользователей предыдущих по отношению к свежим на дату написания статьи версиям операционных систем Windows (Windows 7 (вики: с 22.10.2009 г.), Windows Server 2008 R2 (вики: с 22.10.2009 г.), Windows Vista (вики: с 30.11.2006 г.), Windows Server 2008 (вики: с 12.12.2008 г.), Windows Server 2003 (вики: с 24.04.2003 г.) и Windows XP (вики: с 24.08.2001 г.)): приложения «Windows Store» поддерживаются, начиная с операционных систем «Windows 8» (вики: с 26.10.2012 г.) и «Windows Server 2012» (вики: с 04.09.2012 г.).

Перед тем, как система запустит поиск DLL, она проверит следующее:

  • если DLL с таким же именем модуля уже загружена в память, система будет использовать загруженную DLL, при этом не будет иметь значения, в каком каталоге эта загруженная DLL находится. Система не станет выполнять других действий по поиску DLL;
  • если DLL есть в списке библиотек DLL, известных той версии операционной системы Windows, в которой запущено приложение, система использует свою копию известной DLL (и свои копии библиотек DLL, от которых эта известная DLL зависит, если таковые имеются) вместо того, чтобы искать эту DLL. Увидеть список известных текущей системе DLL можно, обратившись к следующему ключу реестра: HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerKnownDLLs.

Если система должна выполнить поиск модуля или его зависимостей [других модулей, от которых зависит работа исходного модуля], система всегда будет использовать порядок поиска, предназначенный для приложений «Windows Store», даже если искомая зависимость представляет из себя не код приложения «Windows Store».

Стандартный порядок поиска DLL для приложений «Windows Store»

Если модуль DLL еще не загружен или не находится в списке известных системе DLL, то система начинает поиск в следующих местах в указанном ниже порядке:

  1. Граф зависимостей пакета для процесса. Местом поиска является пакет приложения плюс любые зависимости, отмеченные как <PackageDependency> в разделе <Dependencies> манифеста пакета приложения. Зависимости ищутся системой в том порядке, в котором они появляются в манифесте;
  2. Каталог, из которого был загружен вызывающий DLL процесс;
  3. Системный каталог (%SystemRoot%system32).

Если DLL имеет зависимости [от других DLL], система будет искать библиотеки DLL, от которых зависит исходная, так, как если бы эти библиотеки загружались с указанием только имен их модулей. Это правило остается верным, даже если исходная DLL загружалась с указанием полного пути к ней.

Альтернативный порядок поиска DLL для приложений «Windows Store»

Если модуль меняет стандартный порядок поиска DLL посредством вызова функции LoadLibraryEx с флагом LOAD_WITH_ALTERED_SEARCH_PATH, система ищет в каталоге, из которого указанный [в параметре функции LoadLibraryEx] модуль был загружен, вместо каталога вызывающего процесса. Система выполняет поиск в следующих местах в указанном ниже порядке:

  1. Граф зависимостей пакета для процесса. Местом поиска является пакет приложения плюс любые зависимости, отмеченные как <PackageDependency> в разделе <Dependencies> манифеста пакета приложения. Зависимости ищутся системой в том порядке, в котором они появляются в манифесте;
  2. Каталог, из которого указанный [в параметре функции LoadLibraryEx] модуль был загружен;
  3. Системный каталог (%SystemRoot%system32).

Порядок поиска DLL для приложений настольного компьютера

Приложения настольного компьютера [desktop applications] могут указывать место, из которого будет загружена DLL, посредством указания полного пути к DLL, могут использовать перенаправление поиска DLL, либо могут использовать манифест. Если ни один из этих методов не используется, система ищет DLL во время загрузки программы так, как описано в этом разделе.

Перед тем, как система запустит поиск DLL, она проверит следующее:

  • если DLL с таким же именем модуля уже загружена в память, система будет использовать загруженную DLL, при этом не будет иметь значения, в каком каталоге эта загруженная DLL находится. Система не станет выполнять других действий по поиску DLL;
  • если DLL есть в списке библиотек DLL, известных той версии операционной системы Windows, в которой запущено приложение, система использует свою копию известной DLL (и свои копии библиотек DLL, от которых эта известная DLL зависит, если таковые имеются) вместо того, чтобы искать эту DLL. Увидеть список известных текущей системе DLL можно, обратившись к следующему ключу реестра: HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerKnownDLLs.

Если DLL имеет зависимости [от других DLL], система будет искать библиотеки DLL, от которых зависит исходная, так, как если бы эти библиотеки загружались с указанием только имен их модулей. Это правило остается верным, даже если исходная DLL загружалась с указанием полного пути к ней.

Важное замечание. Если злоумышленник получит доступ к одному из каталогов, в которых выполняется поиск DLL, он может поместить в этот каталог вредоносную копию искомой DLL. Чтобы узнать способы предотвращения таких атак, читайте статью «Безопасность DLL».

Стандартный порядок поиска DLL для приложений настольного компьютера

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

Безопасный режим поиска DLL по умолчанию включен. Чтобы его выключить, следует создать в реестре параметр HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession ManagerSafeDllSearchMode и установить его значение в 0 (ноль). Вызов функции SetDllDirectory при ее успешном завершении отключает параметр реестра SafeDllSearchMode, в то время как указанный [в параметре функции SetDllDirectory] каталог находится в поисковом списке каталогов и изменяет порядок поиска так, как описано [далее] в этой статье.

Замечание для пользователей операционной системы Windows XP (вики: с 24.08.2001 г.; поддержка этой системы прекращена корпорацией «Microsoft» c 08.04.2014 г.): безопасный режим поиска DLL по умолчанию выключен. Чтобы включить его, следует создать параметр реестра SafeDllSearchMode и установить его значение в 1. Безопасный режим поиска DLL включен по умолчанию, начиная с «Windows XP» с установленным пакетом обновления SP2.

Если параметр реестра SafeDllSearchMode включен, порядок поиска DLL будет следующим:

  1. Каталог, из которого загружено приложение;
  2. Системный каталог [обычно это каталог ..WindowsSystem32, но не всегда]. Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу;
  3. Системный каталог для 16-разрядных библиотек DLL [обычно это каталог ..WindowsSystem, но не всегда]. Не существует функции [из набора Windows API], которая получала бы путь к этому каталогу, но поиск в этом каталоге всё равно выполняется;
  4. Каталог операционной системы Windows [обычно это каталог ..Windows, но не всегда]. Используйте функцию GetWindowsDirectory, чтобы получить путь к этому каталогу;
  5. Текущий каталог;
  6. Каталоги, перечисленные в переменной среды PATH. Заметим, что эта переменная не включает путь, определенный в разрезе каждого приложения ключом реестра App Paths [HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionApp Paths]. Ключ реестра App Paths не используется при поиске DLL.

Если параметр реестра SafeDllSearchMode выключен, порядок поиска DLL будет следующим:

  1. Каталог, из которого загружено приложение;
  2. Текущий каталог;
  3. Системный каталог [обычно это каталог ..WindowsSystem32, но не всегда]. Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу;
  4. Системный каталог для 16-разрядных библиотек DLL [обычно это каталог ..WindowsSystem, но не всегда]. Не существует функции [из набора Windows API], которая получала бы путь к этому каталогу, но поиск в этом каталоге всё равно выполняется;
  5. Каталог операционной системы Windows [обычно это каталог ..Windows, но не всегда]. Используйте функцию GetWindowsDirectory, чтобы получить путь к этому каталогу;
  6. Каталоги, перечисленные в переменной среды PATH. Заметим, что эта переменная не включает путь, определенный в разрезе каждого приложения ключом реестра App Paths [HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionApp Paths]. Ключ реестра App Paths не используется при поиске DLL.

Альтернативный порядок поиска DLL для приложений настольного компьютера

Стандартный порядок поиска DLL, используемый системой, может быть изменен с помощью вызова функции LoadLibraryEx с флагом LOAD_WITH_ALTERED_SEARCH_PATH. Стандартный порядок поиска DLL также может быть изменен с помощью вызова функции SetDllDirectory.

Замечание: стандартный порядок поиска DLL для процесса попадет под влияние вызова функции SetDllDirectory в родительском процессе, если этот вызов был выполнен до запуска текущего процесса.

Замечание для пользователей операционной системы Windows XP (вики: с 24.08.2001 г.; поддержка этой системы прекращена корпорацией «Microsoft» c 08.04.2014 г.): изменение стандартного порядка поиска DLL с помощью вызова функции SetDllDirectory не поддерживалось до «Windows XP» с установленным пакетом обновления SP1.

Если вы включили стратегию альтернативного порядка поиска DLL, она будет продолжать своё действие до того момента, пока все соответствующие исполняемые модули не будут найдены. После того, как система запустит в работу подпрограммы инициализации DLL, она вернется к стратегии стандартного порядка поиска DLL.

Функция LoadLibraryEx поддерживает альтернативный порядок поиска DLL, если она вызывается с флагом LOAD_WITH_ALTERED_SEARCH_PATH и в ее параметре lpFileName указан абсолютный путь.

Заметим, что стратегия стандартного порядка поиска DLL и стратегия альтернативного порядка поиска DLL, установленная функцией LoadLibraryEx с флагом LOAD_WITH_ALTERED_SEARCH_PATH, различаются только в одном: стандартный порядок поиска DLL начинается с каталога вызывающего приложения, а альтернативный порядок поиска DLL начинается с каталога исполняемого модуля, загружаемого функцией LoadLibraryEx.

Если параметр реестра SafeDllSearchMode включен, альтернативный порядок поиска DLL будет следующим:

  1. Каталог, определенный параметром lpFileName функции LoadLibraryEx;
  2. Системный каталог [обычно это каталог ..WindowsSystem32, но не всегда]. Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу;
  3. Системный каталог для 16-разрядных библиотек DLL [обычно это каталог ..WindowsSystem, но не всегда]. Не существует функции [из набора Windows API], которая получала бы путь к этому каталогу, но поиск в этом каталоге всё равно выполняется;
  4. Каталог операционной системы Windows [обычно это каталог ..Windows, но не всегда]. Используйте функцию GetWindowsDirectory, чтобы получить путь к этому каталогу;
  5. Текущий каталог;
  6. Каталоги, перечисленные в переменной среды PATH. Заметим, что эта переменная не включает путь, определенный в разрезе каждого приложения ключом реестра App Paths [HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionApp Paths]. Ключ реестра App Paths не используется при поиске DLL.

Если параметр реестра SafeDllSearchMode выключен, альтернативный порядок поиска DLL будет следующим:

  1. Каталог, определенный параметром lpFileName функции LoadLibraryEx;
  2. Текущий каталог;
  3. Системный каталог [обычно это каталог ..WindowsSystem32, но не всегда]. Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу;
  4. Системный каталог для 16-разрядных библиотек DLL [обычно это каталог ..WindowsSystem, но не всегда]. Не существует функции [из набора Windows API], которая получала бы путь к этому каталогу, но поиск в этом каталоге всё равно выполняется;
  5. Каталог операционной системы Windows [обычно это каталог ..Windows, но не всегда]. Используйте функцию GetWindowsDirectory, чтобы получить путь к этому каталогу;
  6. Каталоги, перечисленные в переменной среды PATH. Заметим, что эта переменная не включает путь, определенный в разрезе каждого приложения ключом реестра App Paths [HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionApp Paths]. Ключ реестра App Paths не используется при поиске DLL.

Функция SetDllDirectory поддерживает альтернативный порядок поиска DLL, если в ее параметре lpPathName указан путь. В этом случае альтернативный порядок поиска DLL будет следующим:

  1. Каталог, из которого загружено приложение;
  2. Каталог, указанный в параметре lpPathName функции SetDllDirectory;
  3. Системный каталог [обычно это каталог ..WindowsSystem32, но не всегда]. Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу;
  4. Системный каталог для 16-разрядных библиотек DLL [обычно это каталог ..WindowsSystem, но не всегда]. Не существует функции [из набора Windows API], которая получала бы путь к этому каталогу, но поиск в этом каталоге всё равно выполняется;
  5. Каталог операционной системы Windows [обычно это каталог ..Windows, но не всегда]. Используйте функцию GetWindowsDirectory, чтобы получить путь к этому каталогу;
  6. Каталоги, перечисленные в переменной среды PATH. Заметим, что эта переменная не включает путь, определенный в разрезе каждого приложения ключом реестра App Paths [HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionApp Paths]. Ключ реестра App Paths не используется при поиске DLL.

Если в параметр lpPathName функции SetDllDirectory передана пустая строка, эта функция удаляет текущий каталог из поискового списка каталогов.

Функция SetDllDirectory в случае своей успешной отработки выключает безопасный режим поиска DLL, а указанный в ее параметре каталог включается в поисковый список каталогов. Чтобы восстановить безопасный режим поиска DLL, основанный на параметре реестра SafeDllSearchMode, и вернуть текущий каталог в поисковый список каталогов, следует вызвать функцию SetDllDirectory с ее параметром lpPathName, установленным в значение NULL.

Порядок поиска DLL с использованием флагов LOAD_LIBRARY_SEARCH

Приложение может определить порядок поиска DLL, используя один или более флагов LOAD_LIBRARY_SEARCH функции LoadLibraryEx. Приложение также может использовать флаги LOAD_LIBRARY_SEARCH в качестве параметра функции SetDefaultDllDirectories, чтобы настроить порядок поиска DLL для процесса. Приложение может задать дополнительные каталоги для настройки порядка поиска DLL, нужных процессу, с помощью функций AddDllDirectory или SetDllDirectory.

Замечание для пользователей предыдущих по отношению к свежим на дату написания статьи версиям операционных систем Windows (Windows 7 (вики: с 22.10.2009 г.), Windows Server 2008 R2 (вики: с 22.10.2009 г.), Windows Vista (вики: с 30.11.2006 г.), Windows Server 2008 (вики: с 12.12.2008 г.)): флаги LOAD_LIBRARY_SEARCH доступны на этих системах, если установлено обновление KB2533623.

Замечание для пользователей операционных систем Windows Server 2003 (вики: с 24.04.2003 г.) и Windows XP (вики: с 24.08.2001 г.): флаги LOAD_LIBRARY_SEARCH в этих системах не поддерживаются.

В каких именно каталогах происходит поиск DLL, зависит от флагов, указанных при вызове функций SetDefaultDllDirectories или LoadLibraryEx. Если используется более, чем один флаг, соответствующие каталоги обыскиваются в следующем порядке:

  1. Каталог, содержащий DLL (флаг LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR). В этом каталоге ищутся только DLL, от которых зависит загружаемая DLL;
  2. Каталог приложения (флаг LOAD_LIBRARY_SEARCH_APPLICATION_DIR);
  3. Пути, явно добавленные с помощью функции AddDllDirectory (флаг LOAD_LIBRARY_SEARCH_USER_DIRS) или функции SetDllDirectory. Если был добавлен больше, чем один путь, порядок, в котором эти пути обыскиваются, является неопределенным;
  4. Системный каталог (флаг LOAD_LIBRARY_SEARCH_SYSTEM32).

Если приложение не производит вызова функции LoadLibraryEx с любым из флагов LOAD_LIBRARY_SEARCH, чтобы настроить порядок поиска DLL для процесса, система ищет библиотеки DLL либо с помощью стандартного порядка поиска, либо с помощью альтернативного порядка поиска.

Собираю всякие разные c++ программки bat-скриптиками под windows и по-человечески make-файлом в linux.

В Windows приходится копировать в папку с исполнимыми файлами все наобходимые dll-ки из тех, что лежат в нестандартных местах и не видны в %PATH%. Сейчас у меня это делается костыльным образом: с помощью MS-овской утилитки depends.exe смотрю от каких dll зависит экзешник (в т.ч. от чего зависят необходимые dll) и всю эту радость ручками дописываю в сборочный скрипт.
Но это во-первых требует времени, во-вторых некрасиво, в третьих список необходимых dll у человека, пытающегося собрать мой исходник может оказаться не таким, какой есть у меня на компе, например у меня boost::locale может требовать ICU а где-нибудь locale могла быть собрана без ICU но с iconv.
Хочется или какую-то утилитку, которая в идеале ищет в указанных ей местах все dll, нужные для работы указанного бинарника и затем копирует это всё в указанное место… или хотя-бы что-то, чем можно вытащить из exe-шника информацию о именах необходимых для работы dll-лек в удобном для последующего ковыряния этого в скрипте виде.
Может кто-нибудь знает что-то подобное?

10 ответов

Luchian Grigore
11 сен. 2011, в 16:42

Поделиться

dumpbin из инструментов Visual Studio (папка VCbin) может помочь здесь:

dumpbin /dependents your_dll_file.dll

JeffRSon
03 фев. 2015, в 17:21

Поделиться

Я могу порекомендовать интересное решение для поклонников Linux. После того, как я изучил это решение, я переключился с DependencyWalker на это.

Вы можете использовать свой любимый ldd поверх связанной с Windows exe, dll.

Для этого вам нужно установить Cygwin (базовая установка, без каких-либо дополнительных пакетов) на вашу Windows, а затем запустить Cygwin Terminal. Теперь вы можете запускать свои любимые команды Linux, в том числе:

$ ldd your_dll_file.dll

UPD: вы можете использовать ldd также через терминал git bash в Windows. Не нужно устанавливать cygwin в случае, если у вас уже установлен git.

troyane
08 окт. 2015, в 14:50

Поделиться

  • Существует программа под названием «Зависит»
  • Если у вас установлен cygwin, ничего проще, чем ldd file.exe

Artyom
11 сен. 2011, в 15:19

Поделиться

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

Проблемы с Dll имеют разные грани. Если вы используете Visual Studio и динамически связываетесь с CRT, вам необходимо распространять DLL-библиотеки CRT. Обновите свой VS, и вы должны распространять другую версию CRT. Просто проверки зависимостей недостаточно, так как вы можете пропустить их. Выполнение полной установки на чистой машине — единственное безопасное решение, IMO.

Если вы не хотите настраивать полноценную тестовую среду и иметь Windows 7, вы можете использовать XP-Mode в качестве начальной чистой машины и XP-More, чтобы дублировать виртуальную машину.

eran
11 сен. 2011, в 16:08

Поделиться

На вашей машине разработки вы можете выполнить программу и запустить Sysinternals Process Explorer. В нижней панели он покажет вам загруженные DLL и текущие пути к ним, что удобно по ряду причин. Если вы выполняете свой пакет развертывания, он будет показывать, какие DLL-ссылки ссылаются на неправильный путь (т.е. Не были правильно упакованы).

В настоящее время наша компания использует проекты установщика Visual Studio для работы с деревом зависимостей и вывода в виде незакрепленных файлов программы. В VS2013 это теперь расширение: https://visualstudiogallery.msdn.microsoft.com/9abe329c-9bba-44a1-be59-0fbf6151054d. Затем мы упаковываем эти незакрепленные файлы в более полный инсталлятор, но, по крайней мере, этот проект устанавливает все зависимости от сетки точек и помещает их в одно место и предупреждает вас, когда что-то не хватает.

Shiv
09 июль 2015, в 02:52

Поделиться

В прошлом (т.е. дни WinXP) я использовал/полагался на DLL Dependency Walker (depend.exe), но бывают случаи, когда я еще не могу определить проблему (-ы) DLL. В идеале мы хотели бы узнать до проверки во время проверки, но если это не решит его (или занять слишком много времени), вы можете попробовать включить «загрузку загрузчика», как описано в http://blogs.msdn.com/b/junfeng/archive/2006/11/20/debugging-loadlibrary-failures.aspx и https://msdn.microsoft.com/en-us/library/windows/hardware/ff556886(v=vs.85).aspx и кратко упоминается LoadLibrary терпит неудачу; GetLastError без помощи

ПРЕДУПРЕЖДЕНИЕ: Я испортил свои Windows в прошлом, обманывая gflag, заставляя его ползти на колени, вы были предупреждены.

Изображение 7370

Примечание. «Захват загрузчика» выполняется для каждого процесса, поэтому включение пользовательского интерфейса не будет проверяться (используйте cdb или glfags -i)

HidekiAI
08 июль 2015, в 17:40

Поделиться

NDepend уже упоминался Джесси (если вы анализируете .NET-код), но позволяет точно объяснить, как это может помочь.

Есть ли программа / script, которая может сканировать исполняемый файл для DLL зависимостей или выполнить программу в «чистой» среде без DLL для тестирования для предотвращения таких ситуаций?

На панели «Свойства проекта NDepend» вы можете определить, какие анализы приложений собираются (зеленым цветом), а NDepend будет выводить сторонние сборки, используемые приложениями (синим цветом). Предоставляется список каталогов, где можно искать приложения и сторонние сборки.

Изображение 7371

Если сторонняя сборка не найдена в этих каталогах, она будет в режиме ошибки. Например, если я удалю каталог .NET Fx C:WINDOWSMicrosoft.NETFrameworkv4.0.30319, я вижу, что сторонние сборки .NET Fx не разрешены:

Изображение 7372

Отказ от ответственности: я работаю для NDepend

Patrick from NDepend team
12 июнь 2017, в 14:48

Поделиться

Если у вас есть исходный код, вы можете использовать ndepend.

http://www.ndepend.com/

Это дорого и делает намного больше, чем анализ зависимостей, поэтому он может быть излишним для того, что вы ищете.

Jesse
14 авг. 2015, в 16:17

Поделиться

Пожалуйста, найдите «depend.exe» в google, это крошечная утилита для обработки этого.

shiying yu
11 сен. 2011, в 14:54

Поделиться

Ещё вопросы

  • 1Доступ к Android Входящие / Сообщения из Активности?
  • 1Влияет ли размер приложения Android на неиспользуемый импорт?
  • 1класс Poco модели MVC, структура, имеющая данные или бизнес-уровень?
  • 0Лучшие практики для динамического создания списка элементов в jquery
  • 1API обнаружения формы: «DOMException: источник портит происхождение»
  • 0Как представить данные двоичного массива байтов в C ++?
  • 1Как я могу подключить свой класс ListAdapter для работы во фрагменте с настроенным классом «Модель» для строк?
  • 1Использование значения символа для создания новых строк в Pandas
  • 1Как получить простой список <T> из Android LiveData <List <T >>?
  • 1Почему PageableListView не имеет конструктора без модели или списка
  • 1Picasso IllegalArgumentException Цель не должна быть нулевой: получить данные из Firebase
  • 1Почему java.nio.SocketChannel не отправляет данные (Jdiameter)?
  • 1как удалить /root/.local/lib/python2.7?
  • 0Раскрывающийся список привязки в Angular JS, имеющий неправильное значение в опции
  • 1Как конвертировать stringVar () из tk в pyqt
  • 1Не удается найти элемент с помощью Selenium
  • 1удаленная отладка Visual Studio 2010: запустить внешнюю программу: каталог не существует
  • 0получить данные единой таблицы формы родительского дочернего запроса таблицы pos_parent_id в качестве дочернего идентификатора
  • 0Лучше ли всегда проверять возвращаемое значение PDOStatement :: execute?
  • 0Многопользовательская архитектура
  • 1C # DataGridView получить выбранный номер строки Исключение
  • 0элемент стиля html, за которым следует определенный класс
  • 0Удержание вектора уникального значения, установленного для выбора цвета с использованием C ++ и OpenGL
  • 1Thread.sleep () не позволяет другим потокам работать?
  • 1TargetInvocationException при запуске проекта на wp7
  • 1Я не понимаю, как использовать «это» и «это» в Java
  • 0Angularjs $ ресурс URL-путь
  • 1Как использовать Фрагмент перехода на Android 8 (API 26, Oreo)
  • 1Раскраска текста RichTextBox имеет другое поведение при добавлении в конструктор Form
  • 0Не можете получить значение из класса в C ++?
  • 0Выбрать и упорядочить список по другому условию (Критерии внутреннего объединения в спящий режим)
  • 0Модель и DataTransformer не работают в Symfony2
  • 1Не удалось создать сборку. Ссылочная сборка «Google.Apis» не имеет строгого имени.
  • 1получение данных из firebase и создание списка с помощью флажка
  • 0Атрибут количества столбцов CSS3
  • 0Кнопка для удаления записи в таблице
  • 1Асинхронная проблема с несколькими задачами
  • 1Лучший способ создать этот класс Locus
  • 0радио выбрано / не выбрано на основе выпадающего списка
  • 0Fusioncharts — 2D Column Stack, отображающий ограниченные записи
  • 0Как выбрать только отфильтрованные данные таблицы в angularjs?
  • 1Как добавить разделитель в нижней части навигации
  • 0angularjs: проверить длину фильтра в повтор
  • 0Ошибка синтаксиса TSQL: отсутствует ‘if’
  • 0Как передать событие, вызванное jQuery, в функцию
  • 0CSS негативное фоновое изображение
  • 0Динамически внедрить PHP, поскольку действие формы перенаправляет на страницу 404
  • 0Php cookie не удаляется / не удаляется — не удается выйти
  • 0создание элемента jQuery, передача значения
  • 1Урожай без потерь в формате JPG без потери EXIF на Android

Понравилась статья? Поделить с друзьями:
  • Как найти своего дневника в аниме
  • Как найти центр масс вектора
  • Как найти приходящие сообщения
  • Как найти собственное предназначение
  • Как найти рад гордо