От новичка до гуру: Курсы программирования на CyberDuff

Ориентация как на 32-битную, так и на 64-битную версии с Visual Studio в одном решении / проекте

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

Предпосылки: c # .NET v2.0 с вызовом p / в сторонние 32-разрядные библиотеки DLL, SQL compact v3.5 SP1 с проектом установки. Прямо сейчас целевая платформа установлена ​​на x86, поэтому ее можно запускать в Windows x64.

Сторонняя компания только что выпустила 64-битные версии своих DLL, и я хочу создать специальную 64-битную программу.

Это поднимает некоторые вопросы, на которые у меня пока нет ответов. Я хочу иметь точно такую ​​же базу кода. Я должен строить со ссылками на 32-битный набор DLL или 64-битный DLL. (И сторонние производители, и SQL Server Compact)

Можно ли решить эту проблему с помощью двух новых наборов конфигураций (Debug64 и Release64)?

Должен ли я создать 2 отдельных проекта установки (стандартные проекты Visual Studio, без Wix или какой-либо другой утилиты), или это можно решить в одном и том же .msi?

Любые идеи и / или рекомендации приветствуются.


  • @Magnus Johansson: вы можете использовать две конфигурации, чтобы выполнить половину своей цели. MSI немного сложнее. 28.09.2008

Ответы:


1

Да, вы можете настроить таргетинг как на x86, так и на x64 с одной и той же базой кода в одном проекте. В общем, все будет просто работать, если вы создадите правильные конфигурации решения в VS.NET (хотя P / Invoke для полностью неуправляемых DLL, скорее всего, потребует некоторого условного кода): элементы, которые, как я обнаружил, требуют особого внимания, следующие:

  • Ссылки на внешние управляемые сборки с тем же именем, но с их собственной конкретной разрядностью (это также относится к сборкам взаимодействия с COM)
  • Пакет MSI (который, как уже отмечалось, должен быть нацелен либо на x86, либо на x64)
  • Любые настраиваемые действия на основе классов установщика .NET в вашем пакете MSI.

Проблема ссылки на сборку не может быть решена полностью в VS.NET, так как это позволит вам только один раз добавить ссылку с заданным именем в проект. Чтобы обойти это, отредактируйте файл проекта вручную (в VS щелкните правой кнопкой мыши файл проекта в обозревателе решений, выберите «Выгрузить проект», затем снова щелкните правой кнопкой мыши и выберите «Изменить»). После добавления ссылки, скажем, на версию сборки x86, ваш файл проекта будет содержать что-то вроде:

<Reference Include="Filename, ..., processorArchitecture=x86">
  <HintPath>C:\path\to\x86\DLL</HintPath>
</Reference>

Оберните этот тег Reference внутри тега ItemGroup, указав конфигурацию решения, к которой он применяется, например:

<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
   <Reference ...>....</Reference>
</ItemGroup>

Затем скопируйте и вставьте весь тег ItemGroup и отредактируйте его, чтобы он содержал сведения о вашей 64-битной DLL, например:

<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
  <Reference Include="Filename, ..., processorArchitecture=AMD64">
     <HintPath>C:\path\to\x64\DLL</HintPath>
   </Reference>
</ItemGroup>

После перезагрузки вашего проекта в VS.NET диалоговое окно «Справочник по сборке» будет немного запутано этими изменениями, и вы можете столкнуться с некоторыми предупреждениями о сборках с неправильным целевым процессором, но все ваши сборки будут работать нормально.

На очереди решение проблемы с MSI, и, к сожалению, для этого потребуется инструмент, отличный от VS.NET: я предпочитаю Advanced Installer для этой цели, поскольку он реализует основной трюк (создайте общий MSI, а также 32-битные и 64-битные специфические MSI и используйте средство запуска установки .EXE для извлечения нужную версию и сделайте необходимые исправления во время выполнения) очень и очень хорошо.

Вероятно, вы можете добиться тех же результатов с помощью других инструментов или инструментария Windows Installer XML (WiX), но Advanced Installer делает все настолько просто (и при этом вполне доступно), что я никогда особо не рассматривал альтернативы.

Одна вещь, для которой вы можете по-прежнему требовать WiX, даже при использовании расширенного установщика, - это настраиваемые действия вашего класса установщика .NET. Хотя тривиально указать определенные действия, которые должны выполняться только на определенных платформах (с использованием условий выполнения VersionNT64 и НЕ VersionNT64, соответственно), встроенные настраиваемые действия AI будут выполняться с использованием 32-разрядной платформы даже на 64-разрядных машинах. .

Это может быть исправлено в будущем выпуске, но на данный момент (или при использовании другого инструмента для создания ваших MSI-файлов с той же проблемой) вы можете использовать поддержку управляемых настраиваемых действий WiX 3.0 для создания DLL действий с надлежащей разрядностью, которая будет выполняться с использованием соответствующего Framework.


Изменить: начиная с версии 8.1.2 Advanced Installer правильно поддерживает 64-разрядные пользовательские действия. С момента моего первоначального ответа его цена, к сожалению, немного выросла, хотя он по-прежнему чрезвычайно выгоден по сравнению с InstallShield и ему подобными ...


Изменить: если ваши библиотеки DLL зарегистрированы в GAC, вы также можете использовать стандартные теги ссылок таким образом (например, SQLite):

<ItemGroup Condition="'$(Platform)' == 'x86'">
    <Reference Include="System.Data.SQLite, Version=1.0.80.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x64'">
    <Reference Include="System.Data.SQLite, Version=1.0.80.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64" />
</ItemGroup>

Условие также сокращается до всех типов сборки, выпуска или отладки и просто определяет архитектуру процессора.

28.09.2008
  • В Visual Studio 2008 я обнаружил, что ‹ItemGroup› не могут быть вложенными. Это решение работало нормально, как только я сделал новые ‹ItemGroup› ниже группы остальных ‹Reference› s. Мне также пришлось сменить x86 на AnyCPU, что, вероятно, связано с историей моего конкретного проекта. 01.10.2010
  • Этот расширенный установщик выглядит довольно круто. 06.11.2010
  • Это может быть глупый вопрос, но как получить доступ к файлу, чтобы отредактировать его вручную? 05.05.2012
  • Чтобы отредактировать файл в VS, щелкните правой кнопкой мыши проект в обозревателе решений и найдите «Выгрузить проект». После того, как проект будет выгружен, снова щелкните его правой кнопкой мыши и выберите «Редактировать‹ имя файла проекта ». После редактирования файла проекта сохраните его, снова щелкните файл проекта правой кнопкой мыши и загрузите его. Если нет опечаток или ошибок, он загрузится снова. Если нет, VS в значительной степени расскажет вам, в чем проблема с файлом. Надеюсь, это поможет! 09.05.2012

  • 2

    Допустим, у вас есть сборки DLL для обеих платформ, и они находятся в следующем месте:

    C:\whatever\x86\whatever.dll
    C:\whatever\x64\whatever.dll
    

    Вам просто нужно отредактировать файл .csproj из этого:

    <HintPath>C:\whatever\x86\whatever.dll</HintPath>
    

    К этому:

    <HintPath>C:\whatever\$(Platform)\whatever.dll</HintPath>
    

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

    28.09.2008
  • Было бы здорово, если бы это сработало, но это не так. По крайней мере не для меня. 21.10.2008
  • Разве это не должно быть: ‹HintPath› C: \ something \ $ (Platform) \ something.dll ‹/HintPath› 11.02.2009
  • Работал для меня нормально в Visual Studio 2008, но не копировал автоматически DLL в целевой каталог сборки, как это делает обычный ‹Reference›. Решение mdb сработало для меня лучше. 01.10.2010

  • 3

    Не уверен в полном ответе на ваш вопрос, но подумал, что хочу указать на комментарий в разделе «Дополнительная информация» страница загрузки SQL Compact 3.5 SP1, если вы смотрите на x64 - надеюсь, это поможет.

    Из-за изменений в SQL Server Compact SP1 и дополнительной поддержки 64-битных версий централизованно устанавливаемые и смешанные среды 32-битной версии SQL Server Compact 3.5 и 64-битной версии SQL Server Compact 3.5 SP1 могут создавать то, что кажется прерывистым. проблемы. Чтобы свести к минимуму вероятность конфликтов и обеспечить независимое от платформы развертывание управляемых клиентских приложений, централизованная установка 64-разрядной версии SQL Server Compact 3.5 SP1 с помощью файла установщика Windows (MSI) также требует установки 32-разрядной версии SQL Server. Компактный файл MSI 3.5 SP1. Для приложений, которым требуется только 64-разрядная версия, можно использовать частное развертывание 64-разрядной версии SQL Server Compact 3.5 с пакетом обновления 1 (SP1).

    Я прочитал это как «включить 32-битные файлы SQLCE а также 64-битные файлы» при распространении для 64-битных клиентов.

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

    28.09.2008

    4

    Одна сборка .Net с зависимостями x86 / x64

    Хотя все остальные ответы дают вам решение для создания разных сборок в зависимости от платформы, я даю вам возможность иметь только конфигурацию «AnyCPU» и создать сборку, которая работает с вашими dll x86 и x64.

    Для этого вам нужно написать код для сантехники.

    Разрешение правильных x86 / x64-dll во время выполнения

    Шаги:

    1. Используйте AnyCPU в csproj
    2. Решите, будете ли вы ссылаться только на x86 или x64 dll в ваших csprojs. Адаптируйте настройки UnitTests к выбранным вами параметрам архитектуры. Это важно для отладки / запуска тестов внутри VisualStudio.
    3. В свойствах справочника установите для Копировать локальную и определенную версию значение false.
    4. Избавьтесь от предупреждений об архитектуре, добавив эту строку в первую PropertyGroup во всех ваших файлах csproj, где вы ссылаетесь на x86 / x64: <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
    5. Добавьте этот сценарий postbuild в свой запускаемый проект, используйте и измените пути этого сценария sp, чтобы он копировал все ваши dll x86 / x64 в соответствующие подпапки вашего сборочного bin \ x86 \ bin \ x64 \

      xcopy /E /H /R /Y /I /D $(SolutionDir)\YourPathToX86Dlls $(TargetDir)\x86 xcopy /E /H /R /Y /I /D $(SolutionDir)\YourPathToX64Dlls $(TargetDir)\x64

      -> Когда вы запустите приложение сейчас, вы получите исключение, что сборка не может быть найдена.

    6. Зарегистрируйте событие AssemblyResolve в самом начале точки входа в ваше приложение.

      AppDomain.CurrentDomain.AssemblyResolve += TryResolveArchitectureDependency;
      

      этим методом:

      /// <summary>
      /// Event Handler for AppDomain.CurrentDomain.AssemblyResolve
      /// </summary>
      /// <param name="sender">The app domain</param>
      /// <param name="resolveEventArgs">The resolve event args</param>
      /// <returns>The architecture dependent assembly</returns>
      public static Assembly TryResolveArchitectureDependency(object sender, ResolveEventArgs resolveEventArgs)
      {
          var dllName = resolveEventArgs.Name.Substring(0, resolveEventArgs.Name.IndexOf(","));
      
          var anyCpuAssemblyPath = $".\\{dllName}.dll";
      
          var architectureName = System.Environment.Is64BitProcess ? "x64" : "x86";
      
          var assemblyPath = $".\\{architectureName}\\{dllName}.dll";
      
          if (File.Exists(assemblyPath))
          {
              return Assembly.LoadFrom(assemblyPath);
          }
      
          return null;
      }
      
    7. Если у вас есть модульные тесты, создайте TestClass с помощью метода, который имеет AssemblyInitializeAttribute, а также зарегистрируйте вышеупомянутый TryResolveArchitectureDependency-Handler там. (Иногда это не будет выполняться, если вы запускаете отдельные тесты внутри Visual Studio, ссылки будут разрешаться не из корзины UnitTest. Поэтому решение на шаге 2 важно.)

    Преимущества:

    • Одна установка / сборка для обеих платформ

    Недостатки: - Отсутствие ошибок во время компиляции, когда dll x86 / x64 не совпадают. - Вы все равно должны запустить тест в обоих режимах!

    При необходимости создайте второй исполняемый файл, который является эксклюзивным для архитектуры x64, с помощью Corflags.exe в сценарии postbuild.

    Другие варианты, которые стоит попробовать: - Вам не нужен обработчик событий AssemblyResolve, если вы гарантируете, что нужные библиотеки DLL копируются в вашу двоичную папку при запуске (Оценить архитектуру процесса -> переместить соответствующие библиотеки DLL из x64 / x86 в папку bin и обратно. ) - В установщике оцените архитектуру и удалите двоичные файлы для неправильной архитектуры и переместите правильные в папку bin.

    03.08.2018

    5

    По поводу вашего последнего вопроса. Скорее всего, вы не сможете решить эту проблему в рамках одного MSI. Если вы используете реестр / системные папки или что-либо подобное, сам MSI должен знать об этом, и вы должны подготовить 64-битный MSI для правильной установки на 32-битном компьютере.

    Существует вероятность того, что вы можете установить свой продукт как 32-битное IT-приложение и по-прежнему иметь возможность запускать его как 64-битное, но я думаю, что этого может быть трудно достичь.

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

    Надеюсь это поможет. Вот ссылка на некоторую информацию, связанную с проблемами 32/64 бит: http://blog.typemock.com/2008/07/registry-on-windows-64-bit-double-your.html

    28.09.2008

    6

    Если вы используете пользовательские действия, написанные на .NET, как часть установщика MSI, у вас возникает другая проблема.

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

    Дополнительная информация и некоторые приемы ниндзя, чтобы обойти (в основном измените MSI, чтобы использовать 64-битную версию этой прокладки)

    Создание MSI в Visual Studio 2005/2008 для работы на SharePoint 64

    64-разрядные управляемые настраиваемые действия с помощью Visual Studio

    26.11.2008

    7

    Вы можете сгенерировать два решения по-разному и потом объединить их! Я сделал это для VS 2010. и это работает. У меня было 2 разных решения, сгенерированных CMake, и я их объединил

    26.07.2012

    8

    Вы можете использовать условие для ItemGroup для ссылок на DLL в файле проекта.
    Это заставит Visual Studio повторно проверять условие и ссылки всякий раз, когда вы меняете активную конфигурацию.
    Просто добавьте условие для каждой конфигурации.

    Пример:

     <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
        <Reference Include="DLLName">
          <HintPath>..\DLLName.dll</HintPath>
        </Reference>
        <ProjectReference Include="..\MyOtherProject.vcxproj">
          <Project>{AAAAAA-000000-BBBB-CCCC-TTTTTTTTTT}</Project>
          <Name>MyOtherProject</Name>
        </ProjectReference>
      </ItemGroup>
    
    11.09.2013
    Новые материалы

    Путь AWS  — «Изучение машинного обучения — 10 начинающих ИИ и машинного обучения на AWS».
    Универсальный ресурсный центр для изучения искусственного интеллекта и машинного обучения. НОЛЬ или ГЕРОЙ, начните свое путешествие здесь. Получите решения и пройдите обучение у экспертов AWS...

    5 простых концепций Python, ставших сложными
    #заранее извините 1) Переменные x = 4 y = 5 Переменная в Python — это символическое представление объекта. После присвоения некоторого объекта переменной Python мы приобретаем..

    «Освоение вероятности: изучение совместной, предельной, условной вероятности и теоремы Байеса —…
    Виды вероятности: Совместная вероятность Предельная вероятность Условная вероятность Диаграмма Венна в вероятностях: В “Set Theory” мы создаем диаграмму Венна...

    Основы Spring: Bean-компоненты, контейнер и внедрение зависимостей
    Как лего может помочь нашему пониманию Когда мы начинаем использовать Spring, нам бросают много терминов, и может быть трудно понять, что они все означают. Итак, мы разберем основы и будем..

    Отслеживание состояния с течением времени с дифференцированием снимков
    Время от времени что-то происходит и революционизирует часть моего рабочего процесса разработки. Что-то более забавное вместо типичного утомительного и утомительного процесса разработки. В..

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

    Игра в прятки с данными
    Игра в прятки с данными Я хотел бы, чтобы вы сделали мне одолжение и ответили на следующие вопросы. Гуглить можно в любое время, здесь никто не забивается. Сколько регионов в Гане? А как..