Выполнение dll. Как установить DLL файл на Windows и зарегистрировать? Скачивание и установка DLL-файлов

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

Именно по этой причине я предлагаю разобрать внимательно запуск DLL в системе Windows разных версий, чтобы не возникла не пришлось целую вечность ломать голову над тем, как от нее избавиться.

Ошибка DLL при запуске игр

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

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

Бывают случаи, что компьютерная игра хочет вызвать функцию, расположенную в DLL библиотеке стороннего производителя. Все происходило замечательно, уже много времени, но вдруг запуска не произошло и на экране стало появляться надоедливое окно с извещением об ошибке. Стали повторять запуск DLL и исследовать ошибку. Оказалось, что разработчик библиотеки просто изъял эту функцию из исходного кода DLL-ки и не потрудился включить этот пункт в состав документации. Пришлось программистам игры срочно выпускать патч и обновлять исходники своего продукта, чтобы геймеры смогли и дальше нормально играть. Или рассмотрим еще вот такой пример.

Здесь мы видим, что игра выдает сообщение об ошибке DLL, которая связана с тем, что она не может найти по указанному пути необходимую ей . ? Да очень просто! Для начала стоит проверить, а есть ли действительно в системе нужная нам DLL-ка. Если таковая имеется, то значит скорее всего она повреждена и игра не может произвести запуск DLL. В этом случае будет целесообразно и зарегистрировать ее в системе. Как это делать мы уже писали, но давайте осветим этот момент еще раз. Нужно в командной строке выполнить команду regsvr32, которая как раз и занимается регистрацией или разрегистрацией библиотек DLL в системе.

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

Универсальное решения для большинства ошибок вида “Запуск программы невозможен, так как на компьютере отсутствует XXXXX.dll. Попробуйте переустановить программу”

На текущий момент в статье имеется решение для следующих DLL:

Решение подходит для Windows 10, Windows 7, 8, XP и т.д. и состоит из четырех шагов:

Появление сообщений о невозможности запуска программ по причине отсутствия той или иной библиотеки не редкое явление. Причинами могут являться:

  • Некорректное обновление Windows
  • Проблема с жестким диском, которая могла повлечь повреждение файла, сюда же можно отнести и вирусы
  • Удаление игр и программ, которые вместе с собой удаляют и системные файлы
  • Установка “дополнений” к Windows из не проверенных источников

Причём вариантов не найденных библиотек масса, а варианты решения для всех отсутствующих библиотек одинаковы:

  1. Переустановить по новой необходимый пакет (дистрибутив, патч и т.п.), частью которого приходится пропавшая DLL
  2. Переписать только не достающий файл и переписать его в систему

И первое и второе можно найти ниже в статье.

Шаг 1. Определяем разрядность Вашей операционной системы

Для этого необходимо нажать правую кнопку мыши на иконке “Компьютер ” и выбрать свойства, либо нажать на сочетание клавиш + Pause Break


Может быть два варианта либо x32 либо x64 . В нашем случае это 32-разрядная система. Запомните Ваше значение, так как в дальнейшем от этого зависит выбор вариантов загрузки файлов.

Шаг 2. Скачиваем необходимые файлы

Для загрузки необходимой динамически подключаемой библиотеки (так называются файлы формата DLL) в сети существует множество веб сайтов, на которых можно найти и скачать необходимую библиотеку, в свою очередь рекомендуем не искать самостоятельно такие сайты, а воспользоваться проверенным ресурсом dll-files.com , так как велика вероятность получить вместо нужного файла вирус или иное вредоносное ПО. Или как вариант загрузить с нашего сайта ниже.

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

Почему нужно переписать оба файла? Дело в приложении, которое у Вас не запускается, оно может быть как x32 так и x64, и чтобы оно наверняка запустилось скачиваем оба.

api-ms-win-crt-runtime-l1-1-0.dll

2. Весь пакет Microsoft Visual C++ Redistributable для Visual Studio 2015 с нашего сайта для полной переустановки:

3. Только необходимые файлы

Является частью пакета Microsoft Visual C++ Redistributable для Visual Studio 2015 . необходим для запуска приложений написанных с использованием Visual Studio 2015

2. Только необходимые файлы

Является частью пакета NVIDIA PhysX отвечающей за реалистичную физику в играх, таких как NFS Shift, Metro 2033 и других

1. Весь пакет с нашего сайта для полной переустановки:

2. Только необходимый файл

Содержится в OpenAL – это кросс платформенная библиотека отвечающая за объемное воспроизведение звука и используется в основном в играх, например, таких как GRID, Minecraft,Football Manager и других

1. Весь пакет с нашего сайта для полной переустановки:

2. Только необходимый файл

Шаг 3. Установка

Если Вы скачали установщик пакета, то просто запускаем и устанавливаем (переустанавливаем) его. И все последующие шаги Вам не нужны.

Если Ваш вариант сам файл библиотеки то читаем дальше.

Как вариант можно попробовать переписать dll файл в папку с игрой или программой, которая не запускается. Windows при запуске программ сперва ищет dll в запускаемой папке, а потом уже переходит для поиска к системным. Да и к тому же этот способ безопасней, так как внося изменения в системные разделы Windows, вероятность краха всей системы.

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


Именно в выделенную папку (как на гифке) и нужно скопировать необходимую dll

Итак, если предыдущий вариант не прошел осознавая возможные риски копируем библиотеки в системные разделы Windows.

Для тех у кого 32-х битная версия:
Копируем файл библиотеки в папку C:\Windows\System32 . Если файл уже существует замените его.

Для тех у кого 64-х битная версия:
Если файл 64-х битный, то копируем его в папку C:\Windows\System32 .
Если файл 32-х битный то в папку c:\Windows\SysWoW64 (именно в этой папке для совместимости в Windows хранятся dll файлы 32-х битной разрядности).

Шаг 4. Регистрация библиотеки

Нажмите на клавиатуре сочетание кнопок + R появится окошко выполнить. В него надо ввести команду regsvr32 имя_вашей_библиотеки (например regsvr32 msvcp140.dll)

Для 32-х битного компьютера:

(например regsvr32 msvcp100.dll)

Для 64-х битного компьютера:

regsvr32 имя_файла_вашей_библиотеки

(например regsvr32 msvcp100.dll) – для регистрации файла версии 64 бит

Снова нажимаем + R и вводим:

%systemroot%\SysWoW64\regsvr32.exe msvcp110.dll

Шаг 5. Перезагружаем компьютер.

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

Запуск программы невозможен, так как на компьютере отсутствует необходимая dll

Дополнительная сложность программ для Windows вызывает появление новых категорий ошибок. Turbo Debugger имеет ряд средств, которые помогут вам найти ошибке в программе для Windows.

Регистрация сообщений

Окно Windows Messages имеет ряд команд для трассировки и проверки получаемых программой оконных сообщений. С его помощью вы можете устанавливать точки останова по сообщениям (выполнение программы будет приостанавливаться при получении сообщения конкретным окном). Вы можете также регистрировать получаемые окном сообщения. Данное окно открывается командой View Message и имеет три области: область выбора окна, область класса сообщения и область регистрации.

Задание окна

Чтобы регистрировать сообщения для конкретного окна, задайте это окно, отслеживаемые сообщения и действия, выполняемые отладчиком при их получении: прерывание выполнения (Break) или регистрация (Log).

Чтобы задать окно в TD32, используйте имя оконной процедуры, которая обрабатывает сообщения окна. Для этого с помощью команды Add в SpeedMenu области выбора окна откройте диалоговое окно Add Window Procedure to Watch (или наберите непосредственно ее имя в области). Затем наберите имя процедуры в поле ввода Window Identifier и нажмите Enter. Эту процедуру вы можете повторить для каждого окна, сообщения которому вы хотите отслеживать.

В TDW окно можно задать с помощью описателя окна или оконной процедуры, обрабатывающей его сообщения. В любом случае следует использовать диалоговое окно Add Window или Handle to Watch. Для его вывода выберите команду Add в SpeedMenu области выбора окна или наберите имя непосредственно в этой области. Кнопки Identify By этих окон позволяет вам выбрать способ спецификации окна. Это меню позволяет также отменить выбор окна. Для этого используются команды Remove (Ctrl+R) и Delete All (Ctrl+D).

Задание отслеживаемых сообщений

После задания окна Turbo Debugger по умолчанию перечисляет в области регистрации сообщения все сообщения WM_. Чтобы сократить число отслеживаемых сообщений, используйте диалоговое окно Set Message Filter, которое выводится командой Add в SpeedMenu области класса сообщения. Это окно позволяет задать класс сообщений или индивидуальные имена сообщений.

Чтобы задать конкретное сообщение для окна в области выбора окна, откройте диалоговое окно Set Message Filter и с помощью кнопки с зависимой фиксации выберите один из следующих классов сообщений:

All Messages Все оконные сообщения.
Mouse Сообщения, генерируемые событием "мыши".
Window Сообщения, генерируемые администратором окон.
Input Сообщения, генерируемые клавиатурным событием, или обращением пользователя к меню System, полосе прокрутки или блоку изменения размера.
System Сообщения, генерируемые изменениями в масштабе системы.
Initialization Сообщения, генерируемые при создании в приложении диалогового окна.
Clipboard Сообщения, генерируемые при обращении пользователя к буферу Clipboard.
DDE Сообщения динамического обмена данными, генерируемые при обмене данными между приложениями Windows.
Non-client Сообщения, генерируемые Windows для обслуживания неклиентной области окна приложения.
Other Любые сообщения, не попадающие в предыдущие категории (например, сообщения MDI).
Single Message Позволяет вам задать конкретное отслеживаемое сообщение.

Чтобы регистрировать одно сообщение, выберите Single Message и введите в поле ввода Single Message Name имя сообщения или его номер. Если вы хотите регистрировать для конкретного окна несколько классов или сообщений, то

  • задайте конкретный класс или имя сообщения;
  • выберите в SpeedMenu области классов сообщений команду Add;
  • в определение отслеживаемых сообщений добавьте классы или имена сообщений.

Задание действия по сообщению

После спецификации окна и отслеживаемых сообщений нужно задать действие, выполняемое при поступлении сообщения. Turbo Debugger предусматривает в диалоговом окне Set Message Filter две кнопки Action: Break (приостановка выполнения программы) и Log (регистрация сообщения вы области регистрации окна Windows Messages). Break фактически означает установку точки останова по сообщения.

Если вы регистрируете сообщения для нескольких окон, не регистрируйте все сообщения. Большое число передаваемых между Windows и Turbo Debugger сообщений может привести к краху системы.

Отладка библиотек DLL

Динамически компонуемая библиотека DLL - это библиотека подпрограмм и ресурсов, компонуемая с приложением Windows на этапе выполнения. Это позволяет подпрограммам использовать одну копию подпрограмм, ресурсов и драйверов устройств. Когда приложению требуется доступ к DLL, Windows проверяет, загружена ли DLL в память. Если это так, то вторая копия не загружается.

DLL может загружаться программой в память двумя различными способами:

  • при загрузке программы (DLL загружается при статической компоновке ее с программой с помощью утилиты IMPLIB);
  • когда ваша программа обращается с вызовом LoadLibrary.

Выполнение DLL по шагам

При пошаговом выполнении функции DLL Turbo Debugger загружает идентификатор DLL, исходный код DLL в окно Windows и позиционирует курсор на вызываемую подпрограмму. Однако, перед загрузкой исходного кода в окно Module должны удовлетворяться следующие условия:

  • DLL должна компилироваться с отладочной информацией.
  • Файл.DLL должен находиться в том же каталоге, что и файл.EXE программы.
  • Должен быть доступен исходный код DLL.

Turbo Debugger ищет исходный код DLL также, как и исходный код программ. Если DLL не содержит отладочной информации, то отладчик не может найти исходный код DLL и открывает окно CPU.

При отладке функции DLL и прохождении с помощью F7 или F8 оператора return ваша программа может начать работать, хотя вы нажали F9. Такое поведение типично при отладке DLL, вызванной из программы без отладочной информации, или когда DLL возвращает управление через функциональный вызов Windows.

Если вы отлаживаете код запуска DLL, перед загрузкой DLL установите точку останова на первой строке программы. Это обеспечит приостановку программы при возврате и DLL.

Доступ к DLL и исходному коду модулей

Хотя Turbo Debugger обеспечивает прозрачное пошаговое выполнение функций DLL, вам может потребоваться доступ к DLL до того, как программа ее вызовет (например, в ней нужно установить точки останова или задать отслеживаемые выражения). Для доступа к выполняемому модулю, отличному от текущего загруженного, откройте с помощью команды View Modules (F3) диалоговое окно Load Module Source or DLL. Это диалоговое окно перечисляет все исходные модули, содержащиеся в текущем загруженном выполняемом файле. Блок списка DLL & Programs показывает все файлы.DLL и.EXE, загруженные Windows. (При работе с TDW в нем также выводятся все загруженные файлы.DRV и.FON.)

Символом точки (.) отмечены DLL, которые могут загружаться в Turbo Debugger (а также DLL с отладочной информацией и исходным кодом). Звездочка (*) показывает, что модуль загружен отладчиком. Так как ваши программы могут загружать DLL с помощью вызова LoadLibrary, в блоке списка могут показываться не все DLL.

Если вам нужен другой модуль исходного кода, подсветите нужный модуль в списке Source Module и используйте кнопку Load (или дважды щелкните на имени модуля "мышью"). Turbo Debugger открывает окно Module и выводит исходный код данного модуля.

Для доступа к выполняемому файлу, отличному от текущего, откройте диалоговое окно Load Module Source or DLL Symbols (F3), подсветите в блоке списка нужный файл и выберите командную кнопку Symbol Load. Turbo Debugger открывает окно Module с исходным кодом первого модуля выполняемого файла.

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

При выполнении по шагам функции DLL отладчик автоматически загружает таблицу идентификаторов и исходный код этой DLL. Чтобы предотвратить это, откройте диалоговое окно Load Module Source or DLL Symbols (F3), подсветите в списке нужную DLL, выберите кнопку No и щелкните "мышью" на OK. Turbo Debugger будет выполнять вызовы DLL как одну команду.

Отладка кода запуска DLL

Когда ваша программа загружает DLL, выполняется код запуска DLL. По умолчанию Turbo Debugger не выполняет по шагам этот код. Однако, если вам нужно проверить корректность загрузки DLL, то нужно отладить код запуска. Отладчик позволяет отлаживать два вида такого кода: код инициализации, непосредственно следующий за LibMain (по умолчанию) и скомпонованный с DLL код ассемблера. Этот код инициализирует процедуры запуска и эмулирует математические пакеты (этот режим отладки выбирается параметром -l командной строки отладчика).

Чтобы начать отладку кода запуска DLL, нужно перезагрузить программу (Run Program Reset или F2), а затем выполнить следующие шаги:

  • вывести диалоговое окно Load Module Source or DLL Symbols (F3);
  • подсветите в блоке списка DLL & Programs DLL, код запуска которой вы хотите отладить;
  • выберите кнопку с зависимой фиксацией Debug Startup (если нужной DLL в списке нет, добавьте ее как описано выше);
  • повторите эти шаги, если нужно задать отладку для нескольких DLL;
  • для перезагрузки приложения выберите команду Run Program Reset или F2.

При отладке имейте в виде следующее:

  • Перед перезагрузкой текущего приложения выполняйте до конца код запуска DLL, иначе Windows может зависнуть.
  • Установка точек останова на первой строке приложения или первой строке после вызова LoadLibrary гарантирует возврат управления в Turbo Debugger.
  • После завершения отладки кода запуска нажмите F9, чтобы пройти его до конца и вернуться в приложение.

Отладка мультинитевых программ

Окно Thread, которое открывается по команде View Thread, поддерживает мультинитевую среду Windows NT. Это окно содержит три области: списка нитей, детализации и информационную.

В информационной области перечисляется общая информация о нити. Поле Last указывает последнюю нить, выполненную перед передачей управления в Turbo Debugger, поле Current показывает нить, которая выводится в окнах отладчика, поле Total - общее число активных программных нитей, а поле Notify - Yes или No для статуса Notifu или Termination отдельных нитей. Общий статус устанавливается с помощью команды All Threads.

Область нитей

В этой области перечисляются все активные нити программы, идентифицируемые по номеру нити (назначаемому Windows NT) и имени. Turbo Debugger генерирует имя нити, когда ваша программа создает нить. Первая создаваемая нить называется Thread 1, затем Thread 2 и т.д. Это имя можно изменить.

Окно Thread содержит единое SpeedMenu, которое активизируется из всех областей и содержит перечисленные ниже команды.

Options Открывает диалоговое окно Thread Options, позволяющее задать параметры отдельных нитей. Кнопка Freeze этого окна позволяет "замораживать" и "размораживать" индивидуальные нити. Включение этой кнопки означает, что нить выполняться не будет. Для выполнения программы необходима хотя бы одна активная нить. Кнопка Notify or Tremination позволяет задать, должен ли отладчик уведомлять вас о завершении текущей (подсвеченной) нити (он генерирует сообщение и активизирует окно Module и CPU с текущим адресом программы). Чтобы задать уведомление для всех нитей, используйте команду меню All Threads. Поле ввода Thread Name позволяет изменить имя текущей нити.
Make Current Команда Make Current позволяет сменить нить, обрабатываемую отладчиком. Подсветите в области Threads List нить, которую вы хотите проверить, и нажмите Ctrl+M (или выберите Make Current).
Inspect Открывает окно Module или CPU, которое показывает для подсвеченной нити текущую точку выполнения. Этой команде эквивалентна клавиша Enter.
All Threads Открывает меню, команды которого относятся ко всем нитям программы. Это команды Thaw, Freeze, Enable Exit Notification и Disable Exit Notification.
Step Позволяет переключаться между All и Single. При выборе All клавиши F7 и F8 приводят к выполнению всех нитей программы, а Single позволяет выполнять только одну нить.

Область детализации

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

Трассировка исключительных ситуаций операционной системы

В TD32 команда OS Exceptoions (в SpeedMenu области кода окна CPU) открывает диалоговое окно Specify Exception Handling, в котором вы можете задать, как Turbo Debugger должен обрабатывать исключительные ситуации операционной системы, генерируемые программой.

В блоке списка Exceptions показаны все исключительные ситуации операционной системы, обрабатываемые отладчиком. Для каждой из них вы можете задать обработку отладчиком или программой обработки исключительных ситуаций. По умолчанию они обрабатываются в Turbo Debugger. Он приостанавливает программу и активизирует окно Module или CPU, устанавливая курсор на соответствующую строку кода.

Чтобы изменить это заданное по умолчанию поведение, откройте окно Specify Exception Handling, подсветите исключительную ситуацию, которую вы хотите обрабатывать вы программе, и щелкните "мышью" на кнопке с независимой фиксацией User Program.

Если вы хотите, чтобы программа обрабатывала все исключительные ситуации операционной системы, используйте кнопку User All.

Задание пользовательских исключительных ситуаций

Поля ввода Range Low и Range High окна Specify Exception Handling позволяет задать исключительные ситуации операционной системы, определенные пользователем. По умолчанию оба эти поля устанавливаются отладчиком в 0. Введите в поле Range Low шестнадцатиричное значение, генерируемое исключительной ситуацией. Если определяется несколько исключительных ситуаций, в поле Range High введите также максимальный номер определенной пользователем исключительной ситуации.

Память и списки модулей

В TDW вы можете записать в окно Log содержимое глобальной и локальной динамической памяти или список используемых программой модулей. Окно Windows Information (доступное с помощью команды Display Windows Info в SpeedMenu окна Log) позволяет выбрать тип выводимого списка и где вы хотите его начать.

Глобальная динамически распределяемая область памяти - это память, которую Windows делает доступной для всех приложений. Эта память используется при распределении ресурсов. Чтобы увидеть список объектов данных в глобальной области, выберите в Windows Information кнопку с зависимой фиксацией Global Heap и щелкните "мышью" на OK. Объекты данных выводятся в окне Log.

Кнопка с зависимой фиксацией Start At позволяет вам выводить список с нужного места динамически распределяемой области (с начала, с конца или с места, заданного начальным описателем, устанавливаемым вызовом GlobalAlloc).

Чтобы вывести список всех задач и модулей DLL, загруженных в Windows, выберите в диалоговом окне Windows Information кнопку Module List, затем OK. Модули будут перечисляться в окне Log.

Отладка объектно-ориентированных программ

В Turbo Debugger предусмотрен ряд средств для отладки объектно-ориентированных программ С++.

Окно Hierarchy

Окно Hierarchy (открываемое командой View Hierarchy) служит для проверки иерархии объектов или классов, которая выводится в графическом виде.

Область классов Область иерархии [*] Class Hierarchy 3 [^][v] Devi e Point GlowGauge Rectangle HorzArrow Device HorzBar TextWindow LinearGauge Range Point Device Range GlowGauge Rectangle Screen Parents of Device TextWindow Range VertArrow Rectangle VertBar Point Screen < >

Область порождающих классов

Это окно выводит наследование классов С++ и, в зависимости от использования в программе множественного наследования, состоит из трех областей.

Область классов

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

SpeedMenu этой области содержит две команды. Команда Inspect (или клавиша Enter) открывает для текущего класса окно Class Inspector. Команда Tree активизирует область иерархии, подсвечивая текущий класс.

Область иерархии

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

Локальное меню этой области содержит две команды. Команда Inspect (или клавиша Enter) открывает для подсвеченного класса окно Class Inspector. При отладке программ С++ с множественным наследованием здесь доступна также команда Parents, включающая и выключающая вывод области порождающих классов окна Hierarchy.

Область порождающих классов

Эта область выводится только для программ с множественным наследованием и при ее разрешении. Для классов, полученных путем множественного наследования, она выводит все производные классы. SpeedMenu этой области содержит единственную команду Inspect. При ее выборе (или нажатии Enter) для подсвеченного класса выводится окно Class Inspector.

Окна Class Inspector

Эти окна позволяют вам вывести детальную информацию по классам С++. Чтобы открыть это окно, выведите окно Hierarchy, подсветите класс и нажмите Enter.

[Ч] Class LinearGauge 4 [^][v] int Range::Low ^ int Range::High int Screen::MaxX v < > class Range *Range::ctr() int Range::GetValue() int Range::GetLow() int Range::GetHigh()

Данное окно содержит две области. В верхней области выводится информация о элементах данных и их типах, в нижней - о функциях-элементах и возвращаемых типах. Однако это окно не отражает данных конкретного экземпляра. Если вы хотите проверить аргументы функцию-элемента, подсветите ее и нажмите Enter. Откроется окно Function Inspector.

Если подсвеченный элемент данных представляет собой указатель на класс, то нажатие Enter открывает другое окно Class Inspector. Таким образом вы можете проверять сложные вложенные классы. Как и в случае других окон Inspector клавиша Esc закрывает текущее окно Inspector, а Alt+F3 закрывает их все.

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

Окна Object Inspector

Это окно используется для просмотра структуры и значений конкретного экземпляра класса. Чтобы открыть данное окно, поместите курсор на конкретный экземпляр класса (в окне Module) и нажмите Ctrl+I.

[*] Inspecting tw 3 [^][v] @75C6:01E8 ^ Screen::MaxX 500 (Ox1F4) Screen::MaxY 512 (Ox200) v < > Screen::Convert @0000:0000 Screen::VertVtoA @0000:0000 Screen::VertAtoV @0000:0000 class TextWindow

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

SpeedMenu верхних двух областей содержат идентичные команды, только область элементов данных содержит дополнительную команду Change.

Range Позволяет вам задать диапазон выводимых элементов массива. Если подсвеченный элемент не является массивом или указателем, то команда недоступна.
Change Позволяет изменить значение подсвеченного элемента данных.
Methods Переключается между Yes (по умолчанию) и No. В состоянии Yes отладчик выводит среднюю область окна Object Inspector с перечислением функций-элементов. No отменяет вывод средней области.
Show Inherited Также переключается между Yes и No. В состоянии Yes показываются все функции-элементы, определенные в классе и наследуемые. No позволяет вывести только функции-элементы, определенные в классе.
Inspect Открывает для текущего подсвеченного элемента окно Inspector. Проверка функции-элемента открывает окно Module, где курсор позиционируется на определяющий эту функцию код.
Descend Работает аналогично команде Inspect SpeedMenu, но заменяет текущее окно Inspector. Это уменьшает число открытых на экране окон inspector.
New Expression Используется для проверки различных выражений. Данные в текущем окне Inspector заменяются данными нового вводимого выражения.
Type Cast Позволяет задавать для текущего подсвеченного элемента данные различного типа. Эта команда полезна, если идентификатор не имеет информации о типе и для явного задания типа указателей.
Hierarchy Открывает окно Hierarchy с наследованием текущего класса.

Отладка резидентных программ и драйверов устройств

С помощью TD.EXE вы можете отлаживать не только обычные выполняемые файлы, но также резидентные в памяти программы (TSR) и драйверы устройств. Вы можете кроме того выполнять сам отладчик, как резидентную программу (в то время, как работаете на уровне DOS или запускаете другие программы).

Что такое резидентная программа?

Резидентными (TSR) называют такие программы, которые остаются в оперативной памяти после того, как они завершат управление. В Borland Си и С++, предусмотрена специальная функция geninterrupt, которая выдает такое программное прерывание.

Резидентная программа состоит из двух частей - рабочей части и резидентной части. Рабочая часть выполняет загрузку резидентной части в память и устанавливает вектор прерываний, который определяет характер вызова резидентной в памяти программы. Если резидентная программа должна вызываться с помощью программного прерывания, то рабочая часть программы помещает адрес резидентной части кода в соответствующий вектор прерывания. Если резидентная программа должна вызываться с помощью оперативной клавиши, то резидентная часть должна модифицировать обработчик прерывания DOS для обработки нажатия соответствующих клавиш (клавиши) на клавиатуре.

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

Тонкость отладки резидентных программ состоит в том, что вы должны иметь возможность отлаживать и резидентную, и рабочую часть программы. Когда выполняется файл.EXE, то выполняется только код рабочей части TSR. Поэтому, когда вы как обычно запускаете отладчик, задав имя файла, вы видите выполнение только рабочей части кода программы: то, как он устанавливает резидентную часть и обработчики прерываний. Чтобы отлаживать резидентную часть, вы должны задать точку останова и сделать резидентным сам отладчик.

Отладка резидентной в памяти программы

Отладка рабочей части резидентной программы эквивалентна отладке любого другого файла. Новое появляется только тогда, когда вы начинаете отлаживать резидентную часть. Давайте рассмотрим процесс отладки резидентной программы.

С помощью Turbo Debugger вы можете отлаживать драйвер клавиатуры. При этом для перемещения по отладчику пользуйтесь "мышью".

  1. При компиляции или ассемблировании резидентной программы обеспечьте наличие в ней отладочной информации.
  2. Запустите отладчик и загрузите программу.
  3. Установите точку останова в начале резидентной части кода.
  4. С помощью команды Run Run запустите рабочую часть программы.
  5. Отладьте рабочую часть программы с помощью обычных методов.
  6. Затем выйдите из TSR. Резидентная часть остается в памяти.
  7. Чтобы сделать резидентным отладчик, выберите команду File Resident. На TSR это не повлияет. После этого вы можете вернуться в DOS и вызвать TSR.
  8. В командной строке DOS нажмите оперативные клавиши вызова резидентной программы и работайте с ней как обычно.
  9. Выйдите из TSR. Теперь выполняется резидентная часть TSR, и отладчик обнаруживает точку останова. Вы можете отлаживать резидентный код.

Второй метод отладки резидентной части TSR предусматривает выполнение ее из командной строки DOS и использование окна CPU отладчика для отладки содержащей TSR области ОЗУ.

  1. Скомпилируйте программу с отладочной информацией.
  2. Используйте утилиту TDSTRIP для удаления из программы таблицы идентификаторов и помещения ее в файл.TDS.
  3. Запустите TSR из командной строки.
  4. Запустите утилиту TDMEM, которая выводит схему использования памяти. Запомните адрес сегмента, где загружена резидентная часть вашей программы.
  5. Загрузите отладчик и с помощью команды File Symbol Load загрузите таблицу идентификаторов TSR (файл.TDS).
  6. Установите в начале резидентной части TSR точку останова.
  7. Чтобы сделать отладчик резидентным, выберите команду File Resident.
  8. В командной строке DOS выполните резидентную часть TSR, нажав ее оперативную клавишу, и работайте с программой как обычно. При обнаружении точки останова отладчик приостанавливает TSR в начале резидентной части. Чтобы облегчить работу, синхронизируйте таблицу идентификаторов с кодом в памяти. Идентификаторы в таблице отстоят друг от друга на корректное число байт, но абсолютный адрес первого идентификатора не определен, так как DOS загрузила резидентную программу по адресу в памяти, отличном от того, с которым она ассемблировалась. Поэтому, чтобы найти первый идентификатор в памяти, используйте команду File Table.
  9. Используйте команду File Table Relocate для помещения первого идентификатора из таблицы идентификаторов в соответствующую ячейку памяти. Таким образом, имеющаяся информация об идентификаторах будет соответствовать вашему коду (программе). Для этого в ответ на подсказку отладчика задайте адрес сегмента Seg вашей резидентной программы, который определен с помощью утилиты TDMEM, плюс шестнадцатиричное значение 10 (для PSP размером 256 байт).

    Дизассемблированные из памяти операторы синхронизированы с информацией из таблицы идентификаторов. В случает наличия исходного файла исходные операторы выводятся на той же строке, что и информация из таблицы идентификаторов.

  10. Для перехода к сегменту оперативной памяти, где находится ваша резидентная программа, используйте команду Goto (клавиши Ctrl-G). Это можно сделать, используя адрес сегмента вашей программы TSR, за которым следует смещение 0000H, или с помощью перехода на конкретную метку вашей программы.
  11. Отладьте резидентную часть программы.

Что такое драйвер устройства?

Драйвер устройства - это набор подпрограмм, используемых операционной системой DOS для управления на нижнем уровне функциями ввода-вывода. Устанавливаемые драйверы устройств (в отличие от драйверов, встроенных в DOS) устанавливаются с помощью включения соответствующих строк, например:

Device = clock.sys

в файл CONFIG.SYS. Когда DOS выполняет операцию ввода-вывода для отдельного символа, она просматривает связанный список заголовков устройств, выполняя поиск устройства с соответствующим логическим именем (например, COM1). В случае драйверов блочно-ориентированных устройств, таких, как драйвер диска, DOS отслеживает, сколько установлено драйверов блочно-ориентированных устройств, и обозначает каждый из них буквой: A - первый установленный драйвер устройства, B - второй и т.д. Когда вы, например, ссылаетесь на дисковод C, DOS знает, что нужно вызвать драйвер третьего блочно-ориентированного устройства.

Связанный список двух заголовков драйвера содержит смещение двух компонентов самого драйвера устройства: подпрограмму функции и подпрограмму обработки прерывания.

Когда DOS определяет, что требуется вызвать данный драйвер устройства, она вызывает драйвер дважды. При первом вызове драйвера DOS общается с подрограммой функции и передает ей указатель на буфер в памяти, который называется заголовком запроса. Этот заголовок запроса содержит информацию о том, какие функции требует выполнить DOS от драйвера устройства. Подпрограмма функции просто сохраняет данный указатель для последующего использования. При втором вызове драйвера устройства DOS вызывает подпрограмму обработки прерывания, которая выполняет реальные функции, заданные DOS в заголовке запроса, например, пересылку символов с диска.

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

Проблема при отладке драйверов устройств состоит в том, что файл.EXE отсутствует, так как для выполнения соответствующих функций драйвер должен быть загружен во время загрузки системы с помощью команды DEVICE = DRIVER.EXT, где EXT - это расширение.SYS, .COM или.BIN. Это означает, что отлаживаемый драйвер устройства уже резидентен в памяти до начала отладки. Следовательно, функции по выполнению загрузки и перемещения таблицы идентификаторов весьма полезны, поскольку они могут восстановить информацию об идентификаторах для дизассемблированного сегмента памяти (когда драйвер загружен). Как мы увидим далее, команда File Resident также очень полезна.

Отладка драйвера устройства

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

  1. Скомпилируйте драйвер с включенной отладочной информацией.
  2. С помощью утилиты TDSTRIP (см. файл TD_UTILS.TXT) выделите из драйвера устройства отладочную информацию.
  3. Скопируйте драйвер устройства на удаленную систему.
  4. Измените файл CONFIG.SYS удаленной системы, чтобы он загружал драйвер удаленной системы. Затем перезагрузите уда ленную систему.
  5. Для получения адреса драйвера загрузите на удаленной системе TDMEM.
  6. Загрузите на удаленной системе TDREMOTE.
  7. Загрузите на локальной системе отладчик, связав его с удаленной системой.
  8. Загрузите в отладчике с помощью команды File Symbol Load таблицу идентификаторов драйвера устройства.
  9. Используйте команду File Table Relocate для помещения первого идентификатора из таблицы идентификаторов в соответствующую ячейку памяти. Таким образом, имеющаяся ин формация об идентификаторах будет соответствовать вашему коду (программе). Для этого в ответ на подсказку отладчика задайте адрес сегмента Seg вашей резидентной программы, который можно определить с помощью TDMEM.
  10. Задайте в начале драйвера устройства точку останова.
  11. Выберите команду File Resident, чтобы сделать резидентным сам отладчик. Это не нарушит резидентности вашего драйвера: когда он будет выполняться в отладчике, он сам станет резидентным при загрузке удаленной системы в результате выполнения файла CONFIG.SYS. Единственная резидентной загрузки отладчика заключается в том, что вы можете перейти обратно в DOS и вызвать ваш драйвер устройства.
  12. Когда вы вернетесь снова к командной строке DOS на уда ленной системе, сделайте что-либо для активизации вашего драйвера устройства. Например, выведите информацию на со ответствующее устройство.
  13. Когда в вашей программе-драйвере встретится точка останова, инициализируется отладчик, а код вашей программы вы ведется в соответствующей точке. Теперь вы можете начать отладку вашей программы. (Кроме того, вы можете повторно войти в отладчик из DOS, дважды нажав клавиши Ctrl-Bre ak.)

Удаленная отладка

Удаленная отладка означает с соответствии со своим названием следующее: вы запускаете отладчик на одном компьютере, а отлаживаемую программу - на другом. Две системы могут соединяться через последовательный порт или через локальную сеть LAN, совместимую с NETBIOS. Удаленную отладку полезно использовать в следующих ситуациях:

  • Вашей программе требуется много памяти, и вы не можете за пускать программу и отладчик на одном компьютере.
  • Ваша программа загружается с отладчиком, но для ее правильного функционирования памяти недостаточно. В этом случае в процессе отладки вы будете получать сообщения об ошибках распределения памяти.
  • Нужно отладить специальные программы (резидентные программы или драйверы устройств).
  • Вы отлаживаете программу Windows.

В случае отладки прикладной программы Window у вас есть выбор: вы можете либо запустить на одной машине программу и отладчик для Windows (TDW), либо запустить Windows, утилиту WREMOTE и прикладную программу на одной машине, а отладчик - на другой.

Требования к программному и аппаратному обеспечению

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

  • Рабочая система с памятью, достаточной для загрузки отладчика (локальная система).
  • Другой компьютер РС (удаленная система), имеющий достаточный для отлаживаемых программ DOS и TDREMOTE объем памяти (или для отлаживаемой программы Windows и WREMOTE). Это удаленная система.

Две системы должны соединяться через последовательный порт нуль-модемным кабелем. При соединении через локальную сеть потребуется программное обеспечение, совместимое с Novell Netware. программное обеспечение, совместимое с Novell Netware (версии IPX и NETBIOS 3.0 или старше).

Запуск сеанса удаленной отладки

Чтобы инициировать сеанс удаленной отладки, подготовке удаленную систему, конфигурируйте и запустите WREMOTE (драйвер удаленной отладки), запустите и конфигурируйте на локальной системе TDW и загрузите программу для отладки.

Удаленная система должна содержать следующие файлы: отлаживаемую программу и все необходимые для нее файлы, WREMOTE.EXE, WRSETUP.EXE (программу конфигурации).

Перед запуском WREMOTE с помощью WRSETUP нужно задать параметры передачи данных. Для последовательного подключения щелкните "мышью" на кнопке Serial, выберите скорость передачи (Baud Rate), выберите Desable Clock Interrupts и порт. В поле ввода Starting Directory введите каталог вашей программы. Если нужно, чтобы WREMOTE после завершения отладчика возвращала управление в Windows, установите Quit When Host Quits. По умолчанию WREMOTE использует COM1 и скорость 192000 бод.

WRSetup Turbo Debugger Setup - File Settings Help - Remote Driver Settings OK Cancel Disable clock interrupts Quit when TD quits Baud rate o 9600 Starting directory: * 19200 o 38400 o 115000 Remote type * Serial o Network Comm port Network remote name: * COM1 o COM2

При использовании связи через сеть щелкните "мышью" на кнопке с независимой фиксацией Network, в поле ввода Network Remote Name задайте имя удаленной системы (по умолчанию REMOTE), а в поле Starting Directory введите каталог программы. После закрытия окна WRSETUP установки сохраняются в файле TDW.INI.

После настройки конфигурации WREMOTE вы можете загрузить ее, щелкнув "мышью" на пиктограмме Remote Debugging или с помощью команды Windows File Run. Курсор "мыши" изменяет форму, указывая, что он ждет запуска TDW на другом конце.

Запуск TDW

После запуска на удаленной системе TDREMOTE для связи TDW с TDREMOTE его нужно правильно конфигурировать. Проще всего это сделать с помощью команды File Open (но можно использовать и Options Misceeellaneous программы TDWINST). В открывающемся диалоговом окне Load a New Program to Debug щелкните "мышью" на кнопке Session. Открывается окно Set Session Parameters. Щелкните "мышью" на кнопке Serial Remote. Затем выберите порт (Remote Link Port) и скорость передачи (Link Speed). Щелкните "мышью" на OK. (Порты систем могут быть разными, но скорость должна совпадать.)

Для конфигурации TDW на локальной сети NETBIOS запустите на удаленной системе WREMOTE, запустите TDW и выберите File Open. Открывается окно Load a New Program. Чтобы открыть окно Set Session Parameters щелкните "мышью" на кнопке Session. Выберите кнопку Network Remote и задайте имена локальной и удаленной систем (по умолчанию LOCAL и REMOTE). Затем щелкните на OK.

Инициация связи

После настройки TDW для удаленной отладки загрузите программу с помощью диалогового окна Load a New Program to Debug. TDW выводит уведомляющее сообщение. После установления связи выводится обычный экран отладчика, и команды его работают так же. Однако вывод программы на экран и ввод с клавиатуры происходит на удаленной системе.

Автоматическая передача файла

После загрузки программы TDW автоматически определяет, нужно ли пересылать программу на удаленную систему. В отношении загрузки программы в удаленную систему отладчик отличается гибкостью. Сначала он проверяет наличие программы на удаленной системе. Если программы там нет, он передает ее. Если программа на удаленной системе имеется, он анализирует дату и время копии программы на локальной системе и удаленной системе. Если копия на локальной системе более поздняя (новая), чем на удаленной, он предполагает, что вы перекомпилировали и перекомпоновали программу и передает ее по линии связи. Учтите однако, что TDW передает только файлы.EXE.

С самого рождения (или чуть позже) операционная система Windows использовала библиотеки динамической компоновки DLL (Dynamic Link Library), в которых содержались реализации наиболее часто применяемых функций. Наследники Windows - NT и Windows 95, а также OS/2 - тоже зависят от библиотек DLL в плане обеспечения значительной части их функциональных возможностей.

Рассмотрим ряд аспектов создания и использования библиотек DLL:

  • как статически подключать библиотеки DLL;
  • как динамически загружать библиотеки DLL;
  • как создавать библиотеки DLL;
  • как создавать расширения МFC библиотек DLL.

Использование DLL

Практически невозможно создать приложение Windows, в котором не использовались бы библиотеки DLL. В DLL содержатся все функции Win32 API и несчетное количество других функций операционных систем Win32.

Вообще говоря, DLL - это просто наборы функций, собранные в библиотеки. Однако, в отличие от своих статических родственников (файлов. lib), библиотеки DLL не присоединены непосредственно к выполняемым файлам с помощью редактора связей. В выполняемый файл занесена только информация об их местонахождении. В момент выполнения программы загружается вся библиотека целиком. Благодаря этому разные процессы могут пользоваться совместно одними и теми же библиотеками, находящимися в памяти. Такой подход позволяет сократить объем памяти, необходимый для нескольких приложений, использующих много общих библиотек, а также контролировать размеры ЕХЕ-файлов.

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

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

Библиотеки импортирования

При статическом подключении DLL имя.lib-файла определяется среди прочих параметров редактора связей в командной строке или на вкладке "Link" диалогового окна "Project Settings" среды Developer Studio. Однако.lib-файл, используемый при неявном подключении DLL, - это не обычная статическая библиотека. Такие.lib-файлы называются библиотеками импортирования (import libraries). В них содержится не сам код библиотеки, а только ссылки на все функции, экспортируемые из файла DLL, в котором все и хранится. В результате библиотеки импортирования, как правило, имеют меньший размер, чем DLL-файлы. К способам их создания вернемся позднее. А сейчас рассмотрим другие вопросы, касающиеся неявного подключения динамических библиотек.

Согласование интерфейсов

При использовании собственных библиотек или библиотек независимых разработчиков придется обратить внимание на согласование вызова функции с ее прототипом.

Если бы мир был совершенен, то программистам не пришлось бы беспокоиться о согласовании интерфейсов функций при подключении библиотек - все они были бы одинаковыми. Однако мир далек от совершенства, и многие большие программы написаны с помощью различных библиотек без C++.

По умолчанию в Visual C++ интерфейсы функций согласуются по правилам C++. Это значит, что параметры заносятся в стек справа налево, вызывающая программа отвечает за их удаление из стека при выходе из функции и расширении ее имени. Расширение имен (name mangling) позволяет редактору связей различать перегруженные функции, т.е. функции с одинаковыми именами, но разными списками аргументов. Однако в старой библиотеке С функции с расширенными именами отсутствуют.

Хотя все остальные правила вызова функции в С идентичны правилам вызова функции в C++, в библиотеках С имена функций не расширяются. К ним только добавляется впереди символ подчеркивания (_).

Если необходимо подключить библиотеку на С к приложению на C++, все функции из этой библиотеки придется объявить как внешние в формате С:

Extern "С" int MyOldCFunction(int myParam);

Объявления функций библиотеки обычно помещаются в файле заголовка этой библиотеки, хотя заголовки большинства библиотек С не рассчитаны на применение в проектах на C++. В этом случае необходимо создать копию файла заголовка и включить в нее модификатор extern "C" к объявлению всех используемых функций библиотеки. Модификатор extern "C" можно применить и к целому блоку, к которому с помощью директивы #tinclude подключен файл старого заголовка С. Таким образом, вместо модификации каждой функции в отдельности можно обойтись всего тремя строками:

Extern "С" { #include "MyCLib.h" }

В программах для старых версий Windows использовались также соглашения о вызове функций языка PASCAL для функций Windows API. В новых программах следует использовать модификатор winapi, преобразуемый в _stdcall. Хотя это и не стандартный интерфейс функций С или C++, но именно он используется для обращений к функциям Windows API. Однако обычно все это уже учтено в стандартных заголовках Windows.

Загрузка неявно подключаемой DLL

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

  • Каталог, в котором находится ЕХЕ-файл.
  • Текущий каталог процесса.
  • Системный каталог Windows.

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

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

Динамическая загрузка и выгрузка DLL

Вместо того, чтобы Windows выполняла динамическое связывание с DLL при первой загрузке приложения в оперативную память, можно связать программу с модулем библиотеки во время выполнения программы (при таком способе в процессе создания приложения не нужно использовать библиотеку импорта). В частности, можно определить, какая из библиотек DLL доступна пользователю, или разрешить пользователю выбрать, какая из библиотек будет загружаться. Таким образом можно использовать разные DLL, в которых реализованы одни и те же функции, выполняющие различные действия. Например, приложение, предназначенное для независимой передачи данных, сможет в ходе выполнения принять решение, загружать ли DLL для протокола TCP/IP или для другого протокола.

Загрузка обычной DLL

Первое, что необходимо сделать при динамической загрузке DLL, - это поместить модуль библиотеки в память процесса. Данная операция выполняется с помощью функции ::LoadLibrary , имеющей единственный аргумент - имя загружаемого модуля. Соответствующий фрагмент программы должен выглядеть так:

HINSTANCE hMyDll; :: if((hMyDll=:: LoadLibrary("MyDLL"))==NULL) { /* не удалось загрузить DLL */ } else { /* приложение имеет право пользоваться функциями DLL через hMyDll */ }

Стандартным расширением файла библиотеки Windows считает.dll, если не указать другое расширение. Если в имени файла указан и путь, то только он будет использоваться для поиска файла. В противном случае Windows будет искать файл по той же схеме, что и в случае неявно подключенных DLL, начиная с каталога, из которого загружается exe-файл, и продолжая в соответствии со значением PATH.

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

Если файл обнаружен и библиотека успешно загрузилась, функция ::LoadLibrary возвращает ее дескриптор, который используется для доступа к функциям библиотеки.

Перед тем, как использовать функции библиотеки, необходимо получить их адрес. Для этого сначала следует воспользоваться директивой typedef для определения типа указателя на функцию и определить переменную этого нового типа, например:

// тип PFN_MyFunction будет объявлять указатель на функцию, // принимающую указатель на символьный буфер и выдающую значение типа int typedef int (WINAPI *PFN_MyFunction)(char *); :: PFN_MyFunction pfnMyFunction;

Затем следует получить дескриптор библиотеки, при помощи которого и определить адреса функций, например адрес функции с именем MyFunction:

HMyDll=::LoadLibrary("MyDLL"); pfnMyFunction=(PFN_MyFunction)::GetProcAddress(hMyDll,"MyFunction"); :: int iCode=(*pfnMyFunction)("Hello");

Адрес функции определяется при помощи функции ::GetProcAddress , ей следует передать имя библиотеки и имя функции. Последнее должно передаваться в том виде, в котором экспортируется из DLL.

Можно также сослаться на функцию по порядковому номеру, по которому она экспортируется (при этом для создания библиотеки должен использоваться def-файл, об этом будет рассказано далее):

PfnMyFunction=(PFN_MyFunction)::GetProcAddress(hMyDll, MAKEINTRESOURCE(1));

После завершения работы с библиотекой динамической компоновки, ее можно выгрузить из памяти процесса с помощью функции::FreeLibrary :

::FreeLibrary(hMyDll);

Загрузка MFC-расширений динамических библиотек

При загрузке MFC-расширений для DLL (подробно о которых рассказывается далее) вместо функций LoadLibrary и FreeLibrary используются функции AfxLoadLibrary и AfxFreeLibrary . Последние почти идентичны функциям Win32 API. Они лишь гарантируют дополнительно, что структуры MFC, инициализированные расширением DLL, не были запорчены другими потоками.

Ресурсы DLL

Динамическая загрузка применима и к ресурсам DLL, используемым MFC для загрузки стандартных ресурсов приложения. Для этого сначала необходимо вызвать функцию LoadLibrary и разместить DLL в памяти. Затем с помощью функции AfxSetResourceHandle нужно подготовить окно программы к приему ресурсов из вновь загруженной библиотеки. В противном случае ресурсы будут загружаться из файлов, подключенных к выполняемому файлу процесса. Такой подход удобен, если нужно использовать различные наборы ресурсов, например для разных языков.

Замечание. С помощью функции LoadLibrary можно также загружать в память исполняемые файлы (не запускать их на выполнение!). Дескриптор выполняемого модуля может затем использоваться при обращении к функциям FindResource и LoadResource для поиска и загрузки ресурсов приложения. Выгружают модули из памяти также при помощи функции FreeLibrary .

Пример обычной DLL и способов загрузки

Приведем исходный код динамически подключаемой библиотеки, которая называется MyDLL и содержит одну функцию MyFunction, которая просто выводит сообщение.

Сначала в заголовочном файле определяется макроконтстанта EXPORT . Использование этого ключевого слова при определении некоторой функции динамически подключаемой библиотеке позволяет сообщить компоновщику, что эта функция доступна для использования другими программами, в результате чего он заносит ее в библиотеку импорта. Кроме этого, такая функция, точно так же, как и оконная процедура, должна определяться с помощью константы CALLBACK :

MyDLL.h #define EXPORT extern "C" __declspec (dllexport) EXPORT int CALLBACK MyFunction(char *str);

Файл библиотеки также несколько отличается от обычных файлов на языке C для Windows. В нем вместо функции WinMain имеется функция DllMain . Эта функция используется для выполнения инициализации, о чем будет рассказано позже. Для того, чтобы библиотека осталась после ее загрузки в памяти, и можно было вызывать ее функции, необходимо, чтобы ее возвращаемым значением было TRUE:

MyDLL.c #include #include "MyDLL.h" int WINAPI DllMain(HINSTANCE hInstance, DWORD fdReason, PVOID pvReserved) { return TRUE; } EXPORT int CALLBACK MyFunction(char *str) { MessageBox(NULL,str,"Function from DLL",MB_OK); return 1; }

После трансляции и компоновки этих файлов появляется два файла - MyDLL.dll (сама динамически подключаемая библиотека) и MyDLL.lib (ее библиотека импорта).

Пример неявного подключения DLL приложением

Приведем теперь исходный код простого приложения, которое использует функцию MyFunction из библиотеки MyDLL.dll:

#include #include "MyDLL.h" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int iCode=MyFunction("Hello"); return 0; }

Эта программа выглядит как обычная программ для Windows, чем она в сущности и является. Тем не менее, следует обратить внимание, что в исходный ее текст помимо вызова функции MyFunction из DLL-библиотеки включен и заголовочный файл этой библиотеки MyDLL.h. Также необходимо на этапе компоновки приложения подключить к нему библиотеку импорта MyDLL.lib (процесс неявного подключения DLL к исполняемому модулю).

Чрезвычайно важно понимать, что сам код функции MyFunction не включается в файл MyApp.exe. Вместо этого там просто имеется ссылка на файл MyDLL.dll и ссылка на функцию MyFunction, которая находится в этом файле. Файл MyApp.exe требует запуска файла MyDLL.dll.

Заголовочный файл MyDLL.h включен в файл с исходным текстом программы MyApp.c точно так же, как туда включен файл windows.h. Включение библиотеки импорта MyDLL.lib для компоновки аналогично включению туда всех библиотек импорта Windows. Когда программа MyApp.exe работает, она подключается к библиотеке MyDLL.dll точно так же, как ко всем стандартным динамически подключаемым библиотекам Windows.

Пример динамической загрузки DLL приложением

Приведем теперь полностью исходный код простого приложения, которое использует функцию MyFunction из библиотеки MyDLL.dll, используя динамическую загрузку библиотеки:

#include typedef int (WINAPI *PFN_MyFunction)(char *); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HINSTANCE hMyDll; if((hMyDll=LoadLibrary("MyDLL"))==NULL) return 1; PFN_MyFunction pfnMyFunction; pfnMyFunction=(PFN_MyFunction)GetProcAddress(hMyDll,"MyFunction"); int iCode=(*pfnMyFunction)("Hello"); FreeLibrary(hMyDll); return 0; }

Создание DLL

Теперь, познакомившись с принципами работы библиотек DLL в приложениях, рассмотрим способы их создания. При разработке приложении функции, к которым обращается несколько процессов, желательно размещать в DLL. Это позволяет более рационально использовать память в Windows.

Проще всего создать новый проект DLL с помощью мастера AppWizard, который автоматически выполняет многие операции. Для простых DLL, таких как рассмотренные в этой главе, необходимо выбрать тип проекта Win32 Dynamic-Link Library. Новому проекту будут присвоены все необходимые параметры для создания библиотеки DLL. Файлы исходных текстов придется добавлять к проекту вручную.

Если же планируется в полной мере использовать функциональные возможности MFC, такие как документы и представления, или намерены создать сервер автоматизации OLE, лучше выбрать тип проекта MFC AppWizard (dll). В этом случае, помимо присвоения проекту параметров для подключения динамических библиотек, мастер проделает некоторую дополнительную работу. В проект будут добавлены необходимые ссылки на библиотеки MFC и файлы исходных текстов, содержащие описание и реализацию в библиотеке DLL объекта класса приложения, производного от CWinApp .

Иногда удобно сначала создать проект типа MFC AppWizard (dll) в качестве тестового приложения, а затем - библиотеку DLL в виде его составной части. В результате DLL в случае необходимости будет создаваться автоматически.

Функция DllMain

Большинство библиотек DLL - просто коллекции практически независимых друг от друга функций, экспортируемых в приложения и используемых в них. Кроме функций, предназначенных для экспортирования, в каждой библиотеке DLL есть функция DllMain . Эта функция предназначена для инициализации и очистки DLL. Она пришла на смену функциям LibMain и WEP , применявшимся в предыдущих версиях Windows. Структура простейшей функции DllMain может выглядеть, например, так:

BOOL WINAPI DllMain (HANDLE hInst,DWORD dwReason, LPVOID IpReserved) { BOOL bAllWentWell=TRUE; switch (dwReason) { case DLL_PROCESS_ATTACH: // Инициализация процесса. break; case DLL_THREAD_ATTACH: // Инициализация потока. break; case DLL_THREAD_DETACH: // Очистка структур потока. break; case DLL_PROCESS_DETACH: // Очистка структур процесса. break; } if(bAllWentWell) return TRUE; else return FALSE; }

Функция DllMain вызывается в нескольких случаях. Причина ее вызова определяется параметром dwReason, который может принимать одно из следующих значений.

При первой загрузке библиотеки DLL процессом вызывается функция DllMain с dwReason, равным DLL_PROCESS_ATTACH. Каждый раз при создании процессом нового потока DllMainO вызывается с dwReason, равным DLL_THREAD_ATTACH (кроме первого потока, потому что в этом случае dwReason равен DLL_PROCESS_ATTACH).

По окончании работы процесса с DLL функция DllMain вызывается с параметром dwReason, равным DLL_PROCESS_DETACH. При уничтожении потока (кроме первого) dwReason будет равен DLL_THREAD_DETACH.

Все операции по инициализации и очистке для процессов и потоков, в которых нуждается DLL, необходимо выполнять на основании значения dwReason, как было показано в предыдущем примере. Инициализация процессов обычно ограничивается выделением ресурсов, совместно используемых потоками, в частности загрузкой разделяемых файлов и инициализацией библиотек. Инициализация потоков применяется для настройки режимов, свойственных только данному потоку, например для инициализации локальной памяти.

В состав DLL могут входить ресурсы, не принадлежащие вызывающему эту библиотеку приложению. Если функции DLL работают с ресурсами DLL, было бы, очевидно, полезно сохранить где-нибудь в укромном месте дескриптор hInst и использовать его при загрузке ресурсов из DLL. Указатель IpReserved зарезервирован для внутреннего использования Windows. Следовательно, приложение не должно претендовать на него. Можно лишь проверить его значение. Если библиотека DLL была загружена динамически, оно будет равно NULL. При статической загрузке этот указатель будет ненулевым.

В случае успешного завершения функция DllMain должна возвращать TRUE. В случае возникновения ошибки возвращается FALSE, и дальнейшие действия прекращаются.

Замечание. Если не написать собственной функции DllMain(), компилятор подключит стандартную версию, которая просто возвращает TRUE.

Экспортирование функций из DLL

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

Метод __declspec (dllexport)

Можно экспортировать функцию из DLL, поставив в начале ее описания модификатор __declspec (dllexport) . Кроме того, в состав MFC входит несколько макросов, определяющих __declspec (dllexport), в том числе AFX_CLASS_EXPORT, AFX_DATA_EXPORT и AFX_API_EXPORT.

Метод __declspec применяется не так часто, как второй метод, работающий с файлами определения модуля (.def), и позволяет лучше управлять процессом экспортирования.

Файлы определения модуля

Синтаксис файлов с расширением.def в Visual C++ достаточно прямолинеен, главным образом потому, что сложные параметры, использовавшиеся в ранних версиях Windows, в Win32 более не применяются. Как станет ясно из следующего простого примера, .def-файл содержит имя и описание библиотеки, а также список экспортируемых функций:

MyDLL.def LIBRARY "MyDLL" DESCRIPTION "MyDLL - пример DLL-библиотеки" EXPORTS MyFunction @1

В строке экспорта функции можно указать ее порядковый номер, поставив перед ним символ @. Этот номер будет затем использоваться при обращении к GetProcAddress (). На самом деле компилятор присваивает порядковые номера всем экспортируемым объектам. Однако способ, которым он это делает, отчасти непредсказуем, если не присвоить эти номера явно.

В строке экспорта можно использовать параметр NONAME. Он запрещает компилятору включать имя функции в таблицу экспортирования DLL:

MyFunction @1 NONAME

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

При использовании вышеприведенного def-файл описания экспортируемых функций DLL-библиотеки может быть,например, не таким:

#define EXPORT extern "C" __declspec (dllexport) EXPORT int CALLBACK MyFunction(char *str); a таким: extern "C" int CALLBACK MyFunction(char *str);

Экспортирование классов

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

Если взглянуть на реализованный в классе файл распределения памяти, в нем можно заметить некоторые весьма необычные функции. Оказывается, здесь есть неявные конструкторы и деструкторы, функции, объявленные в макросах MFC, в частности _DECLARE_MESSAGE_MAP, а также функции, которые написанные программистом.

Хотя можно экспортировать каждую из этих функций в отдельности, есть более простой способ. Если в объявлении класса воспользоваться макромодификатором AFX_CLASS_EXPORT, компилятор сам позаботится об экспортировании необходимых функций, позволяющих приложению использовать класс, содержащийся в DLL.

Память DLL

В отличие от статических библиотек, которые, по существу, становятся частью кода приложения, библиотеки динамической компоновки в 16-разрядных версиях Windows работали с памятью несколько иначе. Под управлением Win 16 память DLL размещалась вне адресного пространства задачи. Размещение динамических библиотек в глобальной памяти обеспечивало возможность совместного использования их различными задачами.

В Win32 библиотека DLL располагается в области памяти загружающего ее процесса. Каждому процессу предоставляется отдельная копия "глобальной" памяти DLL, которая реинициализируется каждый раз, когда ее загружает новый процесс. Это означает, что динамическая библиотека не может использоваться совместно, в общей памяти, как это было в Winl6.

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

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

#pragma data_seg(".myseg") int sharedlnts ; // другие переменные общего пользования #pragma data_seg() #pragma comment(lib, "msvcrt" "-SECTION:.myseg,rws");

Все переменные, объявленные между директивами #pragma data_seg(), размещаются в сегменте.myseg. Директива #pragma comment () - не обычный комментарий. Она дает указание библиотеке выполняющей системы С пометить новый раздел как разрешенный для чтения, записи и совместного доступа.

Полная компиляция DLL

Если проект динамической библиотеки создан с помощью AppWizard и.def-файл модифицирован соответствующим образом - этого достаточно. Если же файлы проекта создаются вручную или другими способами без помощи AppWizard, в командную строку редактора связей следует включить параметр /DLL. В результате вместо автономного выполняемого файла будет создана библиотека DLL.

Если в.def-файле есть строка LIBRART, указывать явно параметр /DLL в командной строке редактора связей не нужно.

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

DLL и MFC

Программист не обязан использовать MFC при создании динамических библиотек. Однако использование MFC открывает ряд очень важных возможностей.

Имеется два уровня использования структуры MFC в DLL. Первый из них - это обычная динамическая библиотека на основе MFC, MFC DLL (regular MFC DLL). Она может использовать MFC, но не может передавать указатели на объекты MFC между DLL и приложениями. Второй уровень реализован в динамических расширениях MFC (MFC extensions DLL). Использование этого вида динамических библиотек требует некоторых дополнительных усилий по настройке, но позволяет свободно обмениваться указателями на объекты MFC между DLL и приложением.

Обычные MFC DLL

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

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

Если приложению необходимо обмениваться с DLL указателями на объекты классов MFC или их производных, нужно использовать расширение DLL, описанное в следующем разделе.

Архитектура обычных DLL рассчитана на использование другими средами программирования, такими как Visual Basic и PowerBuilder.

При создании обычной библиотеки MFC DLL с помощью AppWizard выбирается новый проект типа MFC AppWizard (dll) . В первом диалоговом окне мастера приложений необходимо выбрать один из режимов для обычных динамических библиотек: "Regular DLL with MFC statistically linked" или "Regular DLL using shared MFC DLL". Первый предусматривает статическое, а второй - динамическое подключение библиотек MFC. Впоследствии режим подключения MFC к DLL можно будет изменить с помощью комбинированного списка на вкладке "General" диалогового окна "Project settings".

Управление информацией о состоянии MFC

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

AFX_MANAGE_STATE(AfxGetStaticModuleState()) ;

Данный оператор определяет использование соответствующей информации о состоянии во время выполнения функции, обратившейся к данной подпрограмме.

Динамические расширения MFC

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

Чтобы обеспечить возможность свободного обмена указателями на объекты MFC между приложением и DLL, нужно создать динамическое расширение MFC. DLL этого типа подключаются к динамическим библиотекам MFC так же, как и любые приложения, использующие динамическое расширение MFC.

Чтобы создать новое динамическое расширение MFC, проще всего, воспользовавшись мастером приложении, присвоить проекту тип MFC AppWizard (dll) и на шаге 1 включить режим "MFC Extension DLL". В результате новому проекту будут присвоены все необходимые атрибуты динамического расширения MFC. Кроме того, будет создана функция DllMain для DLL, выполняющая ряд специфических операций по инициализации расширения DLL. Следует обратить внимание, что динамические библиотеки данного типа не содержат и не должны содержать объектов, производных от CWinApp .

Инициализация динамических расширений

Чтобы "вписаться" в структуру MFC, динамические расширения MFC требуют дополнительной начальной настройки. Соответствующие операции выполняются функцией DllMain . Рассмотрим пример этой функции, созданный мастером AppWizard.

Static AFX_EXTENSION_MODULE MyExtDLL = { NULL, NULL } ; extern "C" int APIENTRY DllMain(HINSTANCE hinstance, DWORD dwReason, LPVOID IpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { TRACED("MYEXT.DLL Initializing!\n") ; // Extension DLL one-time initialization AfxInitExtensionModule(MyExtDLL, hinstance) ; // Insert this DLL into the resource chain new CDynLinkLibrary(MyExtDLL); } else if (dwReason == DLL_PROCESS_DETACH) { TRACED("MYEXT.DLL Terminating!\n") ; } return 1; // ok }

Самой важной частью этой функции является вызов AfxInitExtensionModule . Это инициализация динамической библиотеки, позволяющая ей корректно работать в составе структуры MFC. Аргументами данной функции являются передаваемый в DllMain дескриптор библиотеки DLL и структура AFX_EXTENSION_MODULE, содержащая информацию о подключаемой к MFC динамической библиотеке.

Нет необходимости инициализировать структуру AFX_EXTENSION_MODULE явно. Однако объявить ее нужно обязательно. Инициализацией же займется конструктор CDynLinkLibrary . В DLL необходимо создать класс CDynLinkLibrary . Его конструктор не только будет инициализировать структуру AFX_EXTENSION_MODULE, но и добавит новую библиотеку в список DLL, с которыми может работать MFC.

Загрузка динамических расширений MFC

Начиная с версии 4.0 MFC позволяет динамически загружать и выгружать DLL, в том числе и расширения. Для корректного выполнения этих операций над создаваемой DLL в ее функцию DllMain в момент отключения от процесса необходимо добавить вызов AfxTermExtensionModule . Последней функции в качестве параметра передается уже использовавшаяся выше структура AFX_EXTENSION_MODULE. Для этого в текст DllMain нужно добавить следующие строки.

If(dwReason == DLL_PROCESS_DETACH) { AfxTermExtensionModule(MyExtDLL); }

Кроме того, следует помнить, что новая библиотека DLL является динамическим расширением и должна загружаться и выгружаться динамически, с помощью функций AfxLoadLibrary и AfxFreeLibrary ,а не LoadLibrary и FreeLibrary .

Экспортирование функций из динамических расширений

Рассмотрим теперь, как осуществляется экспортирование в приложение функций и классов из динамического расширения. Хотя добавить в DEF-файл все расширенные имена можно и вручную, лучше использовать модификаторы для объявлений экспортируемых классов и функций, такие как AFX_EXT_CLASS и AFX_EXT_API,например:

Class AFX_EXT_CLASS CMyClass: public CObject (// Your class declaration } void AFX_EXT_API MyFunc() ;

Часто задаваемые вопросы

  1. Откройте zip-файл, скачанный с сайт.
  2. Извлеките DLL-файл в любое место на компьютере.
    • Далее мы советуем вам поместить файл в папку той программы, которая запрашивает данный файл. Убедитесь, что вы используете 32-разрядный формат DLL-файла для 32-разрядной программы, а 64-разрядный формат DLL-файла для 64-разрядной программы, иначе может возникнуть ошибка 0xc000007b.
  3. Если вышеописанные действия не решат вашу проблему, поместите файл в системную папку. По умолчанию эта папка находится здесь:
    • C:\Windows\System (Windows 95/98/Me),
      C:\WINNT\System32 (Windows NT/2000), or
      C:\Windows\System32 (Windows XP, Vista, 7, 8, 8.1, 10).
  4. В 64-разрядной версии Windows папка для 32-разрядных DLL-файлов по умолчанию расположена здесь:

C:\Windows\SysWOW64\ , а для 64-разрядных DLL-файлов
C:\Windows\System32\ .

Обязательно перезапишите все существующие файлы (но сохраните резервную копию оригинального файла).

Перезагрузите компьютер.

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

Для 32-разрядных DLL-файлов в 32-разрядных версиях Windows и для 64-разрядных DLL-файлов в 64-разрядных Windows:

  1. Откройте командную строку с повышенными правами.
    • Для этого нажмите Пуск, Все программы, выберите Стандартные, кликните правой кнопкой мышки по Командной Строке, далее нажмите «Запуск от имени администратора».
    • Если вас просят ввести пароль администратора или подтвердить, то введите пароль или нажмите «Разрешить».
  2. Далее введите regsvr32 "filename".dll и нажмите Enter.

Занесение в реестр 32-разрядных DLL-файлов в 64-разрядной версии Windows:

  1. Откройте командную строку с повышенными правами, выполнив вышеописанные действия.
    • cd c:\windows\syswow64\
  2. Далее введите следующее и нажмите Enter:
    • regsvr32 c:\windows\syswow64\"filename".dll

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

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

Dynamic-link library

DLL (англ. Dynamic-link library) - динамическая библиотека

DLL (англ. Dynamic-link library) — понятие операционной системы Microsoft Windows, динамическая библиотека, позволяющая многократное применение различными программными приложениями, понятие операционной системы Microsoft Windows. K DLL относятся также элементы управления ActiveX и драйверы.

Формат файлов DLL придерживается тех же соглашений, что и формат исполняемых файлов EXE, сочетая коды, таблицы и ресурсы.

Цели введения DLL

Первоначально предполагалось, что введение DLL позволит эффективно организовать память и дисковое пространство, используя только одну инстанцию библиотечных модулей для многих приложений. Это было особенно важно для ранних версий Microsoft Windows с жёсткими ограничениями по памяти.

Далее, предполагалось улучшить эффективность разработок и использования системных средств за счёт модульности. Замена DLL-программ с одной версии на другую должна была позволить независимо наращивать систему, не затрагивая приложений. Кроме того библиотеки DLL могли использоваться разнотипными приложениями — например, Microsoft Office, Microsoft Visual Studio и т.п.

В дальнейшем идея модульности выросла в концепцию ActiveX-контролей.

Фактически полных преимуществ от внедрения DLL получить не удалось по причине явления, называемого DLL hell (DLL-евский кошмар). DLL hell возникает, когда несколько приложений требуют одновременно различных версий DLL-библиотек по причине их неполной совместимости, что приводит к серьёзным конфликтам. Когда система выросла до определённых размеров, количество DLL стало превышать многие тысячи, не все из них обладали полной надёжностью и совместимостью, и конфликты типа DLL hell стали возникать очень часто, резко понижая общую надёжность системы. Поздние версии Microsoft Windows стали разрешать параллельное использование разных версий DLL, что свело на нет преимущества изначального принципа модульности.