Устранение неполадок в изолированных приложениях и параллельных сборках C/C++
Загрузка приложения C/C++ может завершиться неудачно, если не будут найдены зависимые библиотеки Visual C++. Перечень ошибок, которые могут возникнуть во время выполнения, приведен в разделе Распространение файлов Visual C++. В этом разделе описаны самые распространенные причины возникновения сбоев при загрузке приложения C/C++ и методы устранения возникших неисправностей.
В случаях, когда возникает сбой в работе приложения, используемого на компьютере, где не установлена среда Visual C++, с выдачей ошибок, описанных в разделе Распространение файлов Visual C++, необходимо произвести несколько проверок для установления причины возникновения ошибки.
Выполните действия, описанные в разделе Основные сведения о зависимостях приложения Visual C++. С помощью иллюстратора функциональных зависимостей можно просмотреть большинство зависимостей для каждого конкретного приложения или DLL. Если некоторые из библиотек DLL отсутствуют, необходимо установить эти библиотеки на компьютер, на котором запускается приложение.
Загрузчик операционной системы использует манифест для загрузки сборок, от которых зависит используемое приложение. Манифест может быть внедрен в двоичный файл в качестве ресурса или сохранен как внешний файл в локальной папке приложения. Чтобы проверить, внедрен ли манифест в двоичный файл, необходимо открыть двоичный файл в Visual Studio и просмотреть все ресурсы этого двоичного файла. Нужно найти ресурс с именем RT_MANIFEST. Если в двоичном файле не удается найти манифест, необходимо отыскать внешний файл с именем: <имя_двоичного_файла>.<расширение>.manifest.
Если манифест не найден, необходимо удостовериться в том, что компоновщик создает манифест для вашего проекта. Для этого проверьте параметр компоновщика Создавать манифест в диалоговом окне Свойства проекта вашего проекта.
Примечание
Построение проектов в Visual C++ без создания манифеста не поддерживается.Каждая программа C/C++, построенная в Visual C++, должна иметь манифест с описанием зависимостей от библиотек Visual C++.
Если манифест внедрен в двоичный файл, убедитесь в том, что указан правильный для этого типа двоичного файла идентификатор RT_MANIFEST. Для приложений идентификатор должен быть равен 1, для большинства библиотек DLL — 2. Если манифест является внешним файлом, откройте его в редакторе XML или текстовом редакторе. Дополнительные сведения о манифестах и правилах развертывания см. в разделе Манифесты.
Примечание
Если в Windows XP в локальной папке приложения имеется внешний манифест, загрузчик операционной системы использует этот манифест вместо манифеста, внедренного в двоичный файл.В Windows Server 2003 и более поздних версиях Windows все обстоит наоборот — внешний манифест не используется, а используется манифест, внедренный в двоичный файл, если он есть.
Рекомендуется внедрять манифесты всех DLL в их двоичные файлы. Внешние манифесты не используются, когда библиотека DLL загружается через вызов LoadLibrary. Дополнительные сведения см. в разделе Манифесты сборок.
Убедитесь в том, что все сборки, перечисленные в манифесте, правильно установлены на компьютере. В манифесте указывается имя каждой сборки, номер версии и архитектура процессора. Если приложение зависит от параллельных сборок, необходимо проверить правильность установки этих сборок на компьютере, чтобы загрузчик операционной системы смог их найти, следуя инструкциям в разделе Процесс поиска сборок. Необходимо помнить о том, что 64-разрядные сборки невозможно загрузить в 32-разрядный процесс и использовать в 32-разрядных операционных системах.
Пример
Предположим, имеется приложение appl.exe, построенное с помощью Visual C++. У этого приложения есть свой манифест, который либо встроен в двоичный файл в качестве ресурса RT_MANIFEST с именем appl.exe и идентификатором, равным 1, либо хранится как внешний файл с именем appl.exe.manifest. Содержимое манифеста может выглядеть следующим образом:
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.xxxxx.y" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>
Этот манифест информирует загрузчик операционной системы о следующем: программа appl.exe зависит от сборки с именем Microsoft.VC90.CRT, версии 9.0.xxxxx.y, и построена для 32-разрядного процессора архитектуры x86.
Зависимая параллельная сборка устанавливается либо в качестве общей, либо в качестве закрытой сборки. Например, Visual Studio 2008 устанавливает сборку CRT в качестве общей параллельной сборки, которую можно найти в каталоге %WINDIR%\WinSxS\x86_Microsoft.VC90.CRT_<версия> при работе в Windows XP или в каталоге %WINDIR%\winsxs\x86_microsoft.vc90.crt_<версия> при работе в Windows Vista.
assembly manifest для общей сборки Visual C++ CRT также устанавливается по адресу %WINDIR%\WinSxS\Manifests\x86_microsoft.vc90.crt_<версия>.manifest при работе в Windows XP или по адресу %WINDIR%\winsxs\Manifests\x86_microsoft.vc90.crt_<версия>.manifest при работе в Windows Vista; он определяет эту сборку и перечисляет ее содержание (библиотеки DLL, которые являются частью этой сборки):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright © 1981-2001 Microsoft Corporation -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<noInheritable/>
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.xxxxx.yy" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
<file name="msvcr90.dll" hash="3ca5156e8212449db6c622c3d10f37d9adb12c66" hashalg="SHA1"/>
<file name="msvcp90.dll" hash="92cf8a9bb066aea821d324ca4695c69e55b27cff" hashalg="SHA1"/>
<file name="msvcm90.dll" hash="7daa93e1195940502491c987ff372190bf199395" hashalg="SHA1"/>
</assembly>
Параллельные сборки могут также использовать файлы конфигурации издателя, называемые также файлами политики издателя, для глобального перенаправления приложений и сборок от одной версии параллельной сборки к другой версии той же сборки. Проверить файлы политики для общей сборки Visual C++ CRT можно в файле %WINDIR%\WinSxS\Policies\x86_policy.9.0.Microsoft.VC90.CRT_<версия>.policy при работе в Windows XP или в файле %WINDIR%\winsxs\Manifests\x86_policy.9.0.microsoft.vc90.crt_<версия>.manifest при работе в Windows Vista, где содержится информация, подобная этой:
</assembly>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright © 1981-2001 Microsoft Corporation -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32-policy" name="policy.9.0.Microsoft.VC90.CRT" version="9.0.xxxxx.yy" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
<bindingRedirect oldVersion="9.0.aaaaa.bbb-9.0.ccccc.d" newVersion="9.0.xxxxx.yy"/>
</dependentAssembly>
</dependency>
</assembly>
Вышеприведенный файл политики указывает на то, что любые приложения или сборки, запрашивающие версию 9.0.aaaaa.bbb этой сборки, должны вместо этого использовать версию 9.0.xxxxx.yy сборки, так как это текущая версия, установленная в системе. Если версия сборки, указанная в манифесте приложения, содержится в файле политики, загрузчик ищет версию этой сборки, указанную в манифесте, в папке WinSxS, и, если эта версия не установлена, загрузка завершится ошибкой. Если же сборка версии 9.0.xxxxx.yy также не установлена, операция загрузки для приложений, запрашивающих сборку версии 9.0.aaaaa.bbb, будет невозможна.
Тем не менее, сборка CRT может также быть установлена в качестве закрытой параллельной сборки в локальной папке приложения. Если операционная система не может найти CRT или любую другую сборку как общую, она начнет искать закрытую сборку. Система выполняет поиск закрытых сборок в следующем порядке:
Проверяет локальную папку приложения на наличие файла манифеста с именем <имясборки>.manifest. В данном примере загрузчик пытается найти файл Microsoft.VC90.CRT.manifest в той же папке, где располагается appl.exe. Если манифест найден, загрузчик загружает библиотеку DLL CRT из папки приложения. Если библиотека DLL CRT не обнаружена, загрузка завершится ошибкой.
Пытается открыть папку <имясборки> в локальной папке приложения appl.exe и, если она существует, загружает файл манифеста <имясборки>.manifest из этой папки. Если манифест найден, загрузчик загружает библиотеку DLL CRT из папки <имясборки>. Если библиотека DLL CRT не обнаружена, загрузка завершится ошибкой.
Более подробное описание механизма поиска зависимых сборок загрузчиком см. в разделе Процесс поиска сборок. Если загрузчик не может найти зависимую сборку как закрытую, загрузка завершится ошибкой и возникнет сообщение "Система не может выполнить заданную программу". Чтобы устранить эту ошибку, зависимые сборки и входящие в их состав библиотеки DLL необходимо устанавливать на компьютер либо в качестве закрытых, либо в качестве общих сборок.
См. также
Основные понятия
Основные понятия, связанные с изолированными приложениями и параллельными сборками
Другие ресурсы
Построение изолированных приложений и параллельных сборок C/C++