Зависит ли приложение от среды, в которой оно было скомпилировано?

У нас есть System.BadImageFormatException в наших установщиках MSI. Я уже читал о целевых фреймворках, но мы уже проверили, и он нацелен на правильные фреймворки (.NET Framework 4.5 то же самое с нашими машинами QA).

У нас точно такие же исходные коды, но результаты установщика msi, скомпилированного нашей "командой сборки", не срабатывают, но установщик msi, скомпилированный нами "dev", работает. Вопрос в том, влияет ли среда, в которой было скомпилировано и скомпилировано приложение, на вывод (например, установщики MSI)?

2 ответа

Некоторые рекомендуемые шаги отладки

Так что это фактический файл MSI, который вызывает эти ошибки, или приложение после установки?

Ниже приведены некоторые мысли и вопросы, которые следует учитывать при попытке отладить такие проблемы (без определенного порядка). Моя ставка на выпуск 3 в этом первом списке:

  1. Это исключение возникает при запуске самого MSI (или это setup.exe?) Или при попытке запустить приложение после установки? Просто чтобы проверить - я предполагаю, что MSI.

  2. У вас есть пользовательские действия в настройках? Если вы управляли пользовательскими действиями в коде MSI, на какие платформы вы ориентируетесь при сборке? Any CPU Я бы предположил? Пожалуйста, подтвердите. Я думаю, что здесь есть некоторые проблемы с COM-взаимодействием, но я не совсем уверен в деталях. Иногда вам может понадобиться выбрать конкретную платформу. В этом случае вы можете получить такие сообщения об ошибках (плохое изображение). См. Раздел " Управляемый код " ниже для получения полной информации об управляемом коде и развертывании, а также о некоторых проблемах, которые могут возникнуть.

  3. Независимо от вышесказанного, в вашем исходном файле WiX, каково значение Platform attribute в Product element? Возможные значения: x86, x64, intel64, intel, arm, ia64, Пожалуйста, сообщите (и попробуйте проверить с другими значениями - например, x86, x64). Это влияет на настройку платформы MSI. Если вы не используете WiX - откройте скомпилированный файл MSI и проверьте сводный поток для Platform установка. Используя Orca это View => Summary Information... - Ищу Platform,

  4. Есть ли у вас какие-либо сканеры вредоносных программ, программное обеспечение для обеспечения безопасности или другие "потенциальные блокировщики" для компиляции и / или установки MSI на вашем компьютере? Или на тестовой системе, где вы пытаетесь установить? (Мы должны всегда упоминать эти проблемы - люди могут тратить дни, если мы этого не делаем - даже если это редко кажется единственной проблемой).

  5. Это локализованный MSI с использованием азиатских символов? (или арабский, или любые другие сложные наборы символов?). Я только что упомянул - честно говоря, я не понимаю, насколько это актуально на 100%, но я хочу уточнить эту "переменную" для вашего сценария (то есть, можем ли мы устранить это как источник потенциальной ошибки). Это обычно вызывает ошибки во время выполнения, а не System.BadImageFormatException вопросы - я верю.

  6. Я предполагаю, что сравнение различных файлов MSI может не работать, потому что один из файлов является " плохим образом "? Ты пробовал? Может быть, это все еще действительный файл структурированного хранилища COM - но msiexec.exe двигатель не может справиться с этим? Если это так, то инструменты могут хорошо читать содержимое файла - я не знаю, попробуйте.

    • Для вашего сценария: я изначально думал, что один скомпилированный MSI ведет себя по-разному в разных местах (средах) - и поэтому предложил проверять наличие повреждений при передаче (проблемы с сетью, проблемы с Samba, проблемы с хранилищем, проблемы с вредоносным ПО и т. Д.) делать бинарный diff для копий в разных местах (сравнение на уровне битов). Поскольку вы, кажется, компилируете два (или более) MSI-файла из одних и тех же источников, такое двоичное сравнение явно бессмысленно. Различия очевидны.

    • Однако " сравнение контента " может вам кое-что сказать - это сравнивает фактический контент в таблицах / потоках внутри MSI. Я думаю, что я добавлю Q/A о том, как сравнивать файлы MSI, на которые я могу ссылаться отсюда (добавлено: Как я могу сравнить содержимое двух (или более) файлов MSI?). Это предполагает, что MSI доступен для чтения - даже если он не работает. Единственный способ узнать это попробовать.

Я надеюсь и верю, что приведенный выше список поможет вам разобраться в вашей проблеме.


Я написал себе со скалы ниже на предмет проблем управляемого кода. Идея состояла в том, чтобы описать пару вопросов для проверки, но это стало длительным обсуждением. Я могу удалить все вещи ниже и, возможно, воскресить это в другом месте. Это может вообще не относиться к вам. Общая тема - управляемый код и как он может выйти из строя новыми и "интересными" способами:


Управляемый код

Это еще один из тех обширных ответов, которые вышли из-под контроля. Я думаю, что это все еще имеет ценность, оставляя это в.

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

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

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

Дружеский совет: для всемирного распространения я бы никогда не использовал управляемый код - хотя он "становится безопаснее" - мы должны признать это. Существует слишком много потенциальных источников ошибок для крупномасштабного дистрибутивного пакета MSI, использующего такие настраиваемые действия (домашние пользователи могут удалять.NET, корпоративные пользователи могут видеть версии.NET отключенными, а полный список проблем ниже, и я боюсь "поймать 22 msgstr "удалить проблемы больше всего на свете - целый раздел об этом ниже и т.д...).

Как я уже сказал, я не эксперт, но есть много и серьезных проблем. Может быть, Крис сможет поправить меня, если они уже "отсортированы". Структура DTF (распространяется вместе с WiX) поддерживает встроенное настраиваемое действие dll управляемого кода внутри обычной оболочки win32 dll. Это помогает надежности. Я выкопаю несколько ссылок здесь для справки. Крис был пионером и первопроходцем здесь.

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

  1. .NET Framework может отсутствовать, отключаться или повреждаться (полностью или в версии, запрошенной / необходимой для вашего кода). Теперь, что если все ваши 3000 корпоративных пакетов имеют dll.NET со встроенным управляемым кодом? Они даже не могут удалить в этом случае - намного меньше обновления. Подробнее ниже в выпуске № 5.

  2. При нацеливании на разные версии среды выполнения.NET с различными настраиваемыми действиями все будут загружать одну и ту же версию CLR. Так они говорят мне (я не мог в это поверить, читая это - пожалуйста, прочитайте это!). Хватит мне бегать по холмам:-). " Это может взорваться любым количеством способов " - вот что я думаю о себе. Примените подходящую паранойю соответственно! Обитель зла всех вещей снова поднимает свою уродливую голову - и т.д... Серьезно, не слушайте паранойю, но будьте начеку для серьезных проблем. Эта проблема управляема? Я думаю - я бы сказал да, но это не проблема, чтобы игнорировать. Серьезный UAT / QA необходим во многих различных версиях ОС и.NET. Будет ли родной DLL лучше? Я думаю так.

  3. Компоненты, установленные в GAC, не могут использоваться в качестве зависимостей для ваших управляемых настраиваемых действий в настройке (курица или яйцо - я полагаю). Это связано с моделями коммитов Fusion / MSI.

    • Боб Арнсон прокомментировал это - проверьте это (он в основной команде WiX). Я не знаю, является ли это все еще его главной проблемой с управляемым кодом - наряду с откатом.
    • Небольшое отступление: я читал Арнсона, в котором говорилось, что действия на VBScript хуже, чем на управляемом коде (Painter, конечно, согласен с этим, и определенно сам босс WiX Роб Мэншинг - блог). Я думаю, что это справедливо практически для всех случаев, но не для корпоративных сценариев пакетов приложений (с которыми у меня есть опыт) - или специального тестирования, которое никогда не будет использоваться в производстве (быстро и легко).
      • Я описываю причину этого здесь (прагматическая проблема): установщик Windows не работает на Win 10, но не на Win 7 с использованием WIX (по сути, все, что скомпилировано, добавляет проблему контроля исходного кода в реальном, хаотическом мире - и корпоративные упаковщики должны брать работу друг друга на лету и полностью встроенный, прозрачный исходный файл в MSI экономит время - все время, и есть проблема с набором навыков, и это еще не все...).
      • Я не рекомендую VBScript ни для чего, кроме корпоративного использования в контролируемых средах (стандартизированных рабочих станциях). VBScript недостаточно хорош для публичных релизов MSI по всему миру в любой форме. Они могут работать для пользовательских действий только для чтения, не возвращая кодов ошибок и настроенных на игнорирование всех ошибок времени выполнения, но нет - есть более эффективные способы.
      • ОБНОВЛЕНИЕ: я могу добавить, что в ловушке я использовал бы VBScript в пользовательских действиях только для чтения в последовательности GUI (просто скрипт установщика свойств), чтобы полностью избавиться от.NET framework как зависимости. Придет время, когда.NET Framework будет на всех целевых машинах, но он еще не совсем там (и даже если он там есть, он может быть сломан. Windows теперь активно исправляет ActiveScript, чтобы он всегда работал - и MSI размещает свой собственный ActiveScripting runtime - скрипты будут запускаться, но вы можете легко испортить код, чтобы сделать пользовательские действия еще более ужасными).
      • Я должен добавить, что моя рекомендация использовать Javascript поверх VBScript в ссылке выше будет удалена в ближайшее время. Javascript оказался таким же плохим в практическом использовании, как и VBScript, с некоторыми добавленными ошибками, которые слишком детализированы, чтобы их рассматривать. Расширенная обработка исключений, предлагаемая Javascript, не компенсирует тот факт, что MSI API, по-видимому, был протестирован с VBScript во время его разработки. Javascript, вероятно, не было, и, следовательно, имеет несколько неуклюжих проблем при работе с MSI API, которые не сразу очевидны. Я потратил впустую дорогое время на это - я бы порекомендовал вам не тратить свое впустую.
      • Я также использую сценарии для тестирования, создания прототипов и отладки своих пакетов MSI (для отладки настроек свойств, поиска приложений, переопределения командных строк для тестирования и т. Д.). Я считаю это самым быстрым способом (кто хочет скомпилировать что-то специальное для этого?). Только не катитесь со своим тестовым кодом скрипта для выпуска! При использовании Installshield я использую Installscript для таких "сценариев".
      • И на будущее: одно хорошее применение для управляемого кода будет встроено непосредственно в MSI, в проверяемой (и многократно используемой) форме - создание настраиваемых действий в виде белого окна - со встроенным полным исходным кодом и с полной безопасностью доступа к коду, что делает их неспособными к запуску с бесплатными повышенными правами. Просто подумайте о том, что может произойти - давайте посмотрим, что вы делаете в этом вашем собственном действии?
  4. Чтобы проработать проблему 1, управляемый код может жестко закодировать определенную версию среды выполнения.NET, которая недоступна. Я думаю, что это, вероятно, более легкая проблема для решения? Поправь меня, если я ошибаюсь, Крис. Я просто балуюсь этим. Установка "последней версии" может по-прежнему вызывать проблемы...

  5. Позвольте мне также добавить свою любимую мозоль: если во время удаления происходит сбой управляемого настраиваемого действия из-за поврежденной среды.NET (или по какой-либо другой причине), сосредоточенной на проблемах управляемого кода - например, изменения дизайна / безопасности в самой Windows с Центр обновления Windows) - вы не можете удалить его и, следовательно, (основной) - обновить существующую установку. Серьезный улов 22 на мой взгляд. Попробуйте это, если у вас есть 3000 живых пакетов и тысячи рабочих столов для управления, и dll встроена в каждый MSI...

    • Создание кода произвольного действия любого вида, вызывающего ошибки при удалении / обновлении, было моим большим страхом при создании DLL настраиваемого действия на C++, поэтому он не уникален для управляемого кода. Классическая ошибка заключается в установке пользовательских действий после InstallFinalize или в последовательности пользовательского интерфейса для "проверки кода выхода" - и возвращаемая тривиальная ошибка вызывает полный откат крупного обновления. Классическая "ловушка 22" - теперь вы не можете выполнить обновление без устранения проблемы в последовательности удаления старого продукта.

    • Несмотря на то, что это общая проблема для всего кода настраиваемых действий, я чувствую, что риск значительно повышается с помощью управляемого кода. Что, если какое-то странное изменение политики в.NET Framework делает все пакеты в большой корпорации не удаляемыми и не обновляемыми, так как все они содержат одну и ту же проблематичную пользовательскую операцию DLL? Или, что еще хуже, это изменение дизайна Windows, которое нельзя откатить?

      • В таких случаях должна быть непредвиденная ситуация. Это основная причина, по которой я полностью избегаю управляемого кода - мне больше нравится работать на проводе - меньше слоев зависит от меня. Минимальные зависимости, минимальные запутанности (без имперских запутанностей). Если минимальная зависимость C++ dll не запускается, то ядро ​​Windows, как правило, не работает, и система в любом случае нуждается в перестройке в любом случае. Для пользовательских действий.NET вам, как минимум, придется исправить.NET Framework (что может быть проще, чем я думаю - насколько я знаю - не думаю, что так).

      • Я искал способы сделать DLL-библиотеку внешней для всех корпоративных пакетов в предварительно необходимом пакете (в идеале, с минимальной, базовой линией, встроенной DLL в самой установке - если внешняя DLL отсутствует / не найдена). Идея заключается в том, что внешняя DLL предпочтительнее, если она доступна, и ее можно обновить для всех пакетов с помощью одного обновленного "необходимого пакета". Все 3000 пакетов исправлены - все сразу?

      • Я никогда не удосужился определить техническую осуществимость этого. Терпите меня, я не по теме для вашей цели. Если ребята из WiX читают - каковы технические возможности здесь с вашей головы? По сути, я ожидаю услышать "невозможно" - и тогда я с этим покончил. Размышляя об этом, я готовился к потенциальным проблемам со встроенной DLL в азиатских и арабских странах (потенциально серьезные и неожиданные и фатальные сбои во время выполнения из-за проблем с Unicode / кодовой страницей), а также к любым неожиданным изменениям безопасности в Windows (которые мы сохраняем видя - защита от вымогателей Windows 10, которая в настоящее время периодически вызывает сбой во время выполнения для файлов, установленных в папки userprofile, или внезапную потребность в правах администратора для восстановления MSI - kb2918614, которые появились совершенно неожиданно в Vista, и все остальное, что они продолжают неожиданно меняться...). Я не хотел сидеть с тысячами не обновляемых, неинсталлируемых пакетов - уже развернутых на десятках тысяч компьютеров.

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

      • Я могу придумать, по крайней мере, два других варианта, один из которых - незначительное обновление затронутых пакетов (много работы, чище, гарантированно работает). Последний вариант не будет упомянут:-) - (Волдеморт, " те, о которых мы не говорим " и т. Д.).

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

    • Мои два цента: я могу представить несколько сценариев, где минимальные зависимости важнее, чем для встроенного настраиваемого действия в MSI. Он должен работать на любом компьютере, в любом состоянии, на любом языке, в любом месте, в любом режиме установки (и здесь деинсталляция - подвох 22), в идеале без каких-либо нестандартных зависимостей вообще. По этой причине я статически связываю код C++. Я считаю, что для всемирного распространения это единственная вещь, которая в настоящее время достаточно хороша - статически связанный код C++ - (за возможным исключением Installscript - из Installshield - который теперь работает, по-видимому, без зависимостей - встроенная среда выполнения? Я не знаю, как они Сделайте это - в старые времена были легендарные проблемы с необходимым предварительным условием выполнения для языка Installscript. Это должно быть исправлено начиная с версии 12 Installshield).

  6. Это не полный список. Это мой "список бега за холмами":-).

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

    • Если я на 100% честен, с управляемым кодом все не так плохо, как раньше. Использование DTF и других фреймворков помогло. Но потенциальные проблемы времени выполнения для проблем удаления вызывают беспокойство. Глобальное изменение в.NET Framework в компании - и все ваши пакеты больше не могут быть удалены? Или более новая версия.NET Framework обнаруживает неизвестные ошибки в настраиваемом действии, не обнаруженные при его развертывании? Он может внезапно "проявиться" при попытке удаления / обновления. Управляемый, но ты сам себя проклянешь...

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

    • " Мы никогда не видели никаких проблем с нашими настраиваемыми действиями в управляемом коде " - честно говоря, известными последними словами.

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

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

      • Для всемирной дистрибуции все обстоит иначе, и вещи могут потерпеть неудачу в любом количестве способов, которые трудно отладить, исправить или вообще сработать. Обычно вы вообще не имеете доступа к проблемной системе - для начала. Возможно, прочитайте некоторые дополнительные комментарии в разделе "Сложность развертывания " здесь: установщик Windows и создание WiX.

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

    • Я был бы непредвиденным, что делать, если многие машины подвержены непредвиденным триггерам "тупиков", таким как невозможность удаления / обновления. Некоторая паранойя в этом сценарии, но не невозможная. Глупые "военные игры". Риск - для вашего менеджера, а для вас - для технического.

  7. Добавление ссылки на устаревшую, но все еще действующую запись FAQ с сайта http://www.installsite.org/ по теме управляемых настраиваемых действий и их проблем: как создать настраиваемые действия на управляемых языках, таких как C#?,

  8. И скептически относитесь к любым нестандартным действиям в первую очередь!

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

    • Встроенные конструкции в самом MSI или предварительно написанные пользовательские действия (с поддержкой отката) в таких средах, как WiX или коммерческие инструменты, такие как Installshield и Advanced Installer, были протестированы тысячами, миллионами или даже миллиардами (!) Пользователей - и они написаны лучшими доступными экспертами по развертыванию. Даже для этих компонентов ошибки все еще найдены - этим все сказано. Как вы думаете, вы могли бы сделать это лучше самостоятельно? Всегда отдавайте предпочтение готовым, проверенным и поддерживаемым решениям - если таковые имеются.

    • Рассказ о проблемах с пользовательскими действиями в целом: почему стоит ограничить использование пользовательских действий в моих настройках WiX / MSI?


"Источники"

Некоторые дальнейшие ссылки (некоторые из этого контента могут показывать его возраст к настоящему времени, но это достоверные источники - их нельзя игнорировать - Rob Mensching - доброжелательный диктатор WiX):

Есть две причины этой ошибки:

  1. Кросс-архитектурный вызов из 32-битного кода в 64-битный (или наоборот). Разные архитектуры требуют разных установок MSI Блог Хита Стюартса, и поэтому все в 32-битной установке (особенно в управляемом коде настраиваемых действий) должны быть явно 32-битными и явно 64-битными в 64-битной установке. Например, когда система x64 обнаруживает код AnyCpu, она может загрузить среду выполнения X64, а затем ссылка на 32-разрядную сборку завершится ошибкой и получит эту ошибку.

  2. .NET Framework во время выполнения пытается загрузить "неправильный" фреймворк. Среда выполнения NET 4 в некоторой степени обратно совместима, поэтому вы, скорее всего, получите эту ошибку, когда код, ожидающий, что среда выполнения NET 2 встретит ядро ​​NET 4. Дьявол кроется в деталях, но, опять же, это очень похоже на проблему архитектуры. Если что-то загружает среду выполнения NET 2 и вызывающая последовательность пытается вызвать сборку NET 4 для запуска в 2.0 FW, это сообщение не будет выполнено.

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

Другие вопросы по тегам