Firebird Server Client and VS CRT.
Привет всем.
Сегодня, в очередной раз помогая с устранением проблемы «[dbobj] Загрузка динамической библиотеки «fbclient.dll»», обратил внимание на одну странную несогласованность файлов из дистрибутива Firebird 2.5.2.26539 (разрядность не имеет значения):
- fbclient.dll
- Microsoft.VC80.CRT.manifest
- msvcp80.dll
- msvcr80.dll
fbclient.dll имеет внутри себя манифест вида
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50608.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity> </dependentAssembly> </dependency> </assembly>
То есть он хочет работать с CRT версии 8.0.50608.0
Microsoft.VC80.CRT.manifest описывает CRT с версией 8.0.50608.0
<?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.VC80.CRT" version="8.0.50608.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b" /> <file name="msvcr80.dll"/> <file name="msvcp80.dll"/> <file name="msvcm80.dll"/> </assembly>
А сами файлы msvcp80.dll и msvcr80.dll имеют версию 8.0.50727.42. Внутри манифестов не обнаружено.
Взял нормальный, оригинальный 32х-битный редистр CRT с версией 8.0.50727.42. С помощью Total Commander’a, гугла, 7Zip-а и «понятно кого», вытащил из него манифест с этими двумя DLL. DLL-и с точностью до байта совпали с теми, что я взял из дистрибутива FB. Манифест выглядит так:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <noInheritable></noInheritable> <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.42" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity> <file name="msvcr80.dll" hash="2a0d797a8c5eac76e54e98db9682e0938c614b45" hashalg="SHA1"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>phRUExlAeZ8BwmlD8VlO5udAnRE=</dsig:DigestValue></asmv2:hash></file> <file name="msvcp80.dll" hash="cc4ca55fb6aa6b7bb8577ab4b649ab77e42f8f91" hashalg="SHA1"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>7AY1JqoUvK3u/6bYWbOagGgAFbc=</dsig:DigestValue></asmv2:hash></file> <file name="msvcm80.dll" hash="55e8e87bbde00d1d96cc119ccd94e0c02c9a2768" hashalg="SHA1"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>hWq8zazTsMeKVxWFBa6bnv4hEOw=</dsig:DigestValue></asmv2:hash></file> </assembly>
Попутно я еще обнаружил в этом редистре такой элемент — _14242_policy_8_0_Microsoft_VC80_CRT_x86.msm. Из которого извлек следующий манифест:
<?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.8.0.Microsoft.VC80.CRT" version="8.0.50727.42" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/> <bindingRedirect oldVersion="8.0.41204.256-8.0.50608.0" newVersion="8.0.50727.42"/> </dependentAssembly> </dependency> </assembly>
bindingRedirect, судя по смыслу, говорит что 8.0.50727.42 замещает в том числе и нашу подозрительную 8.0.50608.0.
Тут у меня закралась мысль — а что если проверить клиента с его родным CRT на голой XP? Неужели винда не увидит, что манифест для 8.0.50608.0, а сами DLL имеют версию 8.0.50727.42?
Увы — не увидела! Более того, я потом еще взял и подсунул такие же DLL от 8.0.50727.6195 — fbclient.dll переварил и их тоже. Если заменить манифест, то fbclient.dll, что ожидаемо, перестает грузиться:
[dbobj] Загрузка динамической библиотеки «e:\temp\2013_02_14\fb2\fbclient.dll».
Приложение не было запущено, поскольку оно некорректно настроено. Повторная установка приложения может решить данную проблему.
WIN32 Error: 0x36B1
А вот если установить redistr 8.0.50727.6195 нормальным образом, то fbclient.dll начинает грузиться и работать. Наверное благодаря появившемуся файлу «d:\WINDOWS\WinSxS\Policies\x86_policy.8.0.Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_x-ww_77c24773\8.0.50727.6195.policy» с таким содержимым:
<?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.8.0.Microsoft.VC80.CRT" version="8.0.50727.6195" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/> <bindingRedirect oldVersion="8.0.41204.256-8.0.50608.0" newVersion="8.0.50727.6195"/> <bindingRedirect oldVersion="8.0.50727.42-8.0.50727.6195" newVersion="8.0.50727.6195"/> </dependentAssembly> </dependency> </assembly>
Подведем краткий итог.
1. Сервер скомпилирован для CRT 8.0.50608.0, но поставляется с 8.0.50727.42. И эта странная схема работает.
2. Вместо бинарников 8.0.50727.42 можно положить более свежую версию CRT. И это будет работать, потому что — см. пункт 1.
3. Если установить более новый редистр для VS2005 CRT (версия 8.0.50727.6195 — последняя из мне известных), то этого будет достаточно для работы официальных сборок Firebird 2.5.2 без собственной копии VS2005 CRT. Ну, по крайней мере, клиент точно работает.
Но, не смотря на все эти открытия с заменой, в клиентскую область нашего сайта я положил архивы 32х и 64х битных клиентов для Firebird 2.5.2.26539 с его родным VS CRT. Так что, если у вас есть аккаунт на сайте IBProvider-а, можно загрузить их оттуда. Помимо самих файлов серверного клиента, в архиве лежит readme.txt на изуверском английском, в котором кратно объясняется «что это и как использовать вместо с IBProvider-ом».
Влад on 20 февраля, 2013
Дима, версия бинарника и версия сборки — не есть одно и то же.
Для извлечения манифестов не нужно
>>> Total Commander’a, гугла, 7Zip-а и «понятно кого» <<<
достаточно сделать RTFM и воспользоваться предназначенной для этого утилитой mt 🙂