Устранение неполадок в изолированных приложениях и параллельных сборках C/C++

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

Если приложению не удается загрузиться, так как в его манифесте указана зависимость от параллельной сборки, которая не установлена как закрытая сборка в той же папке, что и исполняемый файл, и в собственном кэше сборок в папке %WINDIR%\WinSxS\ может отображаться одно из следующих сообщений об ошибке в зависимости от версии Windows, в которой вы пытаетесь запустить приложение.

  • Ошибка при инициализации приложения (0xc0000135).

  • Это приложение не удалось запустить из-за неправильной конфигурации. Повторная установка приложения может решить данную проблему.

  • Система не может выполнить указанную программу.

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

  • Не удалось запустить это приложение, так как не была найдена необходимая библиотека DLL. Повторная установка приложения может решить данную проблему.

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

  1. Выполните действия, описанные в разделе Основные сведения о зависимостях приложения Visual C++. Обходчик зависимостей может показать большинство зависимостей для приложения или DLL. Если вы заметили, что некоторые из библиотек DLL отсутствуют, установите их на компьютере, на котором вы пытаетесь запустить приложение.

  2. Загрузчик операционной системы использует манифест приложения для загрузки сборок, от которых зависит приложение. Манифест может быть внедрен в двоичный файл в качестве ресурса либо установлен как отдельный файл в папке приложения. Чтобы проверить, внедрен ли манифест в двоичный файл, откройте двоичный файл в Visual Studio и попробуйте найти RT_MANIFEST в списке ресурсов. Если не удается найти внедренный манифест, найдите в папке приложения файл с именем что-нибудь вроде < binary_name > . < расширение > manifest.

  3. Если приложение зависит от параллельных сборок и манифест отсутствует, необходимо убедиться, что компоновщик создает манифест для вашего проекта. Проверьте параметр компоновщика Создать манифест в диалоговом окне Свойства проекта.

  4. Если манифест внедрен в двоичный файл, проверьте правильность идентификатора RT_MANIFEST для этого типа двоичного файла. Дополнительные сведения о том, какой идентификатор ресурса следует использовать, см. в разделе Использование параллельных сборок в качестве ресурса (Windows). Если манифест находится в отдельном файле, откройте его в редакторе XML или текстовом редакторе. Дополнительные сведения о манифестах и правилах для развертывания см. в разделе Манифесты.

    Примечание

    Если присутствуют одновременно внедренный манифест и отдельный файл манифеста, загрузчик операционной системы использует внедренный манифест и игнорирует отдельный файл. Однако в Windows XP верно обратное — используется отдельный файл манифеста, а внедренный манифест игнорируется.

  5. Мы рекомендуем внедрить манифест в каждую библиотеку DLL, поскольку внешние манифесты опускаются, когда библиотека DLL загружается в вызове LoadLibrary. Дополнительные сведения см. в разделе Манифесты сборки.

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

Пример

Предположим, у нас есть приложение appl.exe, созданное с помощью Visual C++. Манифест приложения внедряется в appl.exe как двоичный ресурс RT_MANIFEST с идентификатором 1 или хранится в виде отдельного файла appl.exe.manifest. Содержимое этого манифеста выглядит следующим образом:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Fabrikam.SxS.Library" version="2.0.20121.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3e"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>

Этот манифест сообщает загрузчику операционной системы, что appl.exe зависит от сборки с именем Fabrikam.SxS.Library, версия 2.0.20121.0, которая разработана для 32-разрядной архитектуры x86. Зависимую параллельную сборку можно установить как общую или закрытую сборку.

Манифест для общей сборки устанавливается в папку %WINDIR%\WinSxS\Manifests\. Он определяет сборку и перечисляет ее содержимое, т. е. библиотеки DLL, входящие в сборку:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
   <noInheritable/>
   <assemblyIdentity type="win32" name="Fabrikam.SxS.Library" version="2.0.20121.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3e"/>
   <file name="Fabrikam.Main.dll" hash="3ca5156e8212449db6c622c3d10f37d9adb1ab12" hashalg="SHA1"/>
   <file name="Fabrikam.Helper.dll" hash="92cf8a9bb066aea821d324ca4695c69e55b2d1c2" hashalg="SHA1"/>
</assembly>

Параллельные сборки могут использовать файлы конфигурации издателя, также называемые файлами политики, чтобы глобально перенаправлять приложения и сборки на использование одной версии параллельной сборки вместо другой версии той же сборки. Политики для общей сборки можно просмотреть в папке %WINDIR%\WinSxS\Policies\. Ниже приведен пример файла политики.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

   <assemblyIdentity type="win32-policy" name="policy.2.0.Fabrikam.SxS.Library" version="2.0.20121.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3e"/>
   <dependency>
      <dependentAssembly>
         <assemblyIdentity type="win32" name="Fabrikam.SxS.Library" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3e"/>
         <bindingRedirect oldVersion="2.0.10000.0-2.0.20120.99" newVersion="2.0.20121.0"/>
      </dependentAssembly>
   </dependency>
</assembly>

Этот файл политики указывает, что любые приложения или сборки, запрашивающие версию 2.0.10000.0 этой сборки, должны использовать версию 2.0.20121.0, т. е. текущую версию, установленную в системе. Если версия сборки, которая упоминается в манифесте приложения, указана в файле политики, загрузчик ищет версию этой сборки, заданную в манифесте, в папке %WINDIR%\WinSxS\. Если эта версия не установлена, загрузка завершится ошибкой. Если же версия сборки 2.0.20121.0 не установлена, загрузка завершится ошибкой для приложений, которые запрашивают версию сборки 2.0.10000.0.

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

  1. Проверьте папку приложения на наличие файла манифеста с именем < AssemblyName > . manifest. В этом примере загрузчик пытается найти Fabrikam.SxS.Library.manifest в папке, содержащую appl.exe. Если манифест найден, загрузчик загружает сборку из папки приложения. Если сборка не найдена, загрузка завершится ошибкой.

  2. Попробуйте открыть папку \ < AssemblyName > \ в папке, содержащей appl.exe, а если \ < AssemblyName > \ существует, попробуйте загрузить файл манифеста с именем < AssemblyName > . manifest из этой папки. Если манифест найден, загрузчик загружает сборку из папки \ < AssemblyName > \. Если сборка не найдена, загрузка завершится ошибкой.

Дополнительные сведения о порядке поиска зависимых сборок загрузчиком см. в разделе Порядок поиска сборок. Если загрузчику не удается найти зависимую сборку как закрытую, загрузка завершится ошибкой и появится сообщение "Система не может выполнить указанную программу". Чтобы устранить эту ошибку, убедитесь, что зависимые сборки (и библиотеки DLL, которые являются их частью) установлены на компьютере как закрытые или общие сборки.

См. также

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