Nhắm mục tiêu cả 32bit và 64bit với Visual Studio trong cùng một giải pháp / dự án


111

Tôi hơi khó xử về cách thiết lập các bản dựng studio trực quan của mình để nhắm mục tiêu đa mục tiêu.

Bối cảnh: c # .NET v2.0 với p / gọi vào DLL 32 bit của bên thứ 3, SQL compact v3.5 SP1, với một dự án Thiết lập. Ngay bây giờ, mục tiêu nền tảng được đặt thành x86 để nó có thể chạy trên Windows x64.

Công ty bên thứ 3 vừa phát hành phiên bản 64 bit của DLL của họ và tôi muốn xây dựng một chương trình 64 bit chuyên dụng.

Điều này đặt ra một số câu hỏi mà tôi vẫn chưa có câu trả lời. Tôi muốn có cùng một cơ sở mã. Tôi phải xây dựng với các tham chiếu đến bộ 32bit của DLL hoặc 64bit của DLL. (Cả bên thứ 3 và SQL Server Compact)

Điều này có thể được giải quyết với 2 bộ cấu hình mới (Debug64 và Release64) không?

Tôi phải tạo 2 dự án thiết lập riêng biệt (dự án studio trực quan, không có Wix hoặc bất kỳ tiện ích nào khác), hay điều này có thể được giải quyết trong cùng một .msi?

Mọi ý tưởng và / hoặc khuyến nghị sẽ được hoan nghênh.


@Magnus Johansson: bạn có thể sử dụng hai cấu hình để hoàn thành một nửa mục tiêu của mình. MSI khó hơn một chút.
user7116 28/09/08

Câu trả lời:


83

Có, bạn có thể nhắm mục tiêu cả x86 và x64 với cùng một cơ sở mã trong cùng một dự án. Nói chung, mọi thứ sẽ Chỉ hoạt động nếu bạn tạo cấu hình giải pháp phù hợp trong VS.NET (mặc dù P / Gọi đến các tệp DLL hoàn toàn không được quản lý rất có thể sẽ yêu cầu một số mã có điều kiện): các mục mà tôi thấy cần chú ý đặc biệt là:

  • Tham chiếu đến các hội đồng được quản lý bên ngoài có cùng tên nhưng có bit cụ thể của riêng chúng (điều này cũng áp dụng cho các hội đồng liên kết COM)
  • Gói MSI (như đã được lưu ý, sẽ cần nhắm mục tiêu x86 hoặc x64)
  • Mọi hành động dựa trên Lớp trình cài đặt .NET tùy chỉnh trong gói MSI của bạn

Vấn đề tham chiếu hợp ngữ không thể được giải quyết hoàn toàn trong VS.NET, vì nó sẽ chỉ cho phép bạn thêm một tham chiếu có tên đã cho vào một dự án một lần. Để giải quyết vấn đề này, hãy chỉnh sửa tệp dự án của bạn theo cách thủ công (trong VS, nhấp chuột phải vào tệp dự án của bạn trong Trình khám phá giải pháp, chọn Dỡ tải dự án, sau đó nhấp chuột phải một lần nữa và chọn Chỉnh sửa). Sau khi thêm tham chiếu tới, chẳng hạn như phiên bản x86 của một assembly, tệp dự án của bạn sẽ chứa một cái gì đó như:

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

Gói thẻ Tham chiếu đó bên trong thẻ ItemGroup cho biết cấu hình giải pháp mà nó áp dụng, ví dụ:

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

Sau đó, sao chép và dán toàn bộ thẻ ItemGroup và chỉnh sửa nó để chứa các chi tiết của DLL 64-bit của bạn, ví dụ:

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

Sau khi tải lại dự án của bạn trong VS.NET, hộp thoại Tham chiếu lắp ráp sẽ hơi bối rối bởi những thay đổi này và bạn có thể gặp một số cảnh báo về các hợp ngữ với bộ xử lý đích sai, nhưng tất cả các bản dựng của bạn sẽ hoạt động tốt.

Việc giải quyết vấn đề MSI sẽ diễn ra tiếp theo, và rất tiếc điều này sẽ yêu cầu công cụ không phải VSNET: Tôi thích Trình cài đặt nâng cao của Caphyon cho mục đích đó, vì nó giải quyết thủ thuật cơ bản liên quan (tạo một MSI chung, cũng như 32-bit và các MSI 64-bit cụ thể và sử dụng trình khởi chạy thiết lập .EXE để trích xuất phiên bản phù hợp và thực hiện các bản sửa lỗi cần thiết trong thời gian chạy) rất tốt.

Bạn có thể đạt được kết quả tương tự bằng cách sử dụng các công cụ khác hoặc bộ công cụ Windows Installer XML (WiX) , nhưng Advanced Installer làm cho mọi thứ trở nên dễ dàng (và giá cả khá phải chăng) mà tôi chưa bao giờ thực sự xem xét các lựa chọn thay thế.

Một điều mà bạn có thể vẫn yêu cầu WiX, ngay cả khi sử dụng Advanced Installer, là cho các hành động tùy chỉnh .NET Installer Class của bạn. Mặc dù việc chỉ định các hành động nhất định chỉ nên chạy trên một số nền tảng nhất định (tương ứng là sử dụng điều kiện thực thi VersionNT64 và NOT VersionNT64) là rất nhỏ, nhưng các hành động tùy chỉnh AI tích hợp sẽ được thực thi bằng Framework 32 bit, ngay cả trên máy 64 bit .

Điều này có thể được khắc phục trong bản phát hành trong tương lai, nhưng hiện tại (hoặc khi sử dụng một công cụ khác để tạo MSI của bạn gặp phải vấn đề tương tự), bạn có thể sử dụng hỗ trợ hành động tùy chỉnh được quản lý của WiX 3.0 để tạo các tệp DLL hành động với độ bit thích hợp sẽ được thực thi bằng Framework tương ứng.


Chỉnh sửa: kể từ phiên bản 8.1.2, Advanced Installer hỗ trợ chính xác các hành động tùy chỉnh 64-bit. Kể từ câu trả lời ban đầu của tôi, giá của nó đã tăng lên khá nhiều, thật không may, mặc dù nó vẫn có giá trị cực kỳ tốt khi so sánh với InstallShield và ilk của nó ...


Chỉnh sửa: Nếu các tệp DLL của bạn được đăng ký trong GAC, bạn cũng có thể sử dụng các thẻ tham chiếu tiêu chuẩn theo cách này (ví dụ về 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>

Điều kiện cũng được giảm xuống cho tất cả các loại xây dựng, phát hành hoặc gỡ lỗi và chỉ xác định kiến ​​trúc bộ xử lý.


Trong Visual Studio 2008, tôi thấy rằng các <ItemGroup> không thể được lồng vào nhau. Giải pháp này hoạt động tốt khi tôi tạo <ItemGroup> mới bên dưới nhóm phần còn lại của <Reference>. Tôi cũng đã phải thay đổi x86 thành AnyCPU, điều này có thể liên quan đến lịch sử của dự án cụ thể của tôi.
Oliver Bock

Trình cài đặt nâng cao đó trông khá tuyệt vời.
Pat

Đây có thể là một câu hỏi ngớ ngẩn nhưng làm thế nào để bạn truy cập tệp để chỉnh sửa nó một cách thủ công?
hrh

1
Để chỉnh sửa tệp trong VS, nhấp chuột phải vào dự án trong Solution Explorer và tìm "Dỡ dự án". Sau khi dự án được dỡ bỏ, nhấp chuột phải vào dự án một lần nữa và nhấp vào "Chỉnh sửa <tên tệp dự án>". Sau khi bạn đã chỉnh sửa tệp dự án, hãy lưu nó và nhấp chuột phải vào tệp dự án một lần nữa và tải nó. Nếu không có lỗi chính tả hoặc lỗi, nó sẽ tải lại. Nếu không, VS sẽ cho bạn biết khá nhiều vấn đề với tệp. Hy vọng rằng sẽ giúp!
John Baughman

Câu trả lời chính xác! Cảm ơn bạn!
John Baughman

27

Giả sử bạn có bản dựng DLL cho cả hai nền tảng và chúng ở vị trí sau:

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

Bạn chỉ cần chỉnh sửa tệp .csproj của mình từ sau:

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

Về điều này:

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

Sau đó, bạn sẽ có thể xây dựng dự án của mình nhắm mục tiêu cả hai nền tảng và MSBuild sẽ tìm trong thư mục chính xác cho nền tảng đã chọn.


Điều này sẽ rất tuyệt nếu nó hoạt động, nhưng nó không. Ít nhất là không phải cho tôi.
John Sheehan

10
Đó không phải là: <HintPath> C: \ anything \ $ (Platform) \ anything.dll </HintPath>
Andreas

Làm việc OK trên Visual Studio 2008 đối với tôi, nhưng không tự động sao chép DLL vào thư mục đích xây dựng, như <Reference> bình thường. giải pháp của mdb làm việc tốt hơn cho tôi.
Oliver Bock

1

Không chắc chắn về tổng số câu trả lời cho câu hỏi của bạn - nhưng tôi nghĩ rằng tôi sẽ chỉ ra một nhận xét trong phần Thông tin bổ sung của trang tải xuống SQL Compact 3.5 SP1 cho thấy bạn đang xem x64 - hy vọng nó sẽ hữu ích.

Do những thay đổi trong SQL Server Compact SP1 và hỗ trợ phiên bản 64-bit bổ sung, môi trường chế độ hỗn hợp và được cài đặt tập trung của phiên bản 32-bit của SQL Server Compact 3.5 và phiên bản 64-bit của SQL Server Compact 3.5 SP1 có thể tạo ra những gì có vẻ không liên tục các vấn đề. Để giảm thiểu khả năng xung đột và cho phép triển khai trung lập nền tảng của các ứng dụng khách được quản lý, cài đặt tập trung phiên bản 64-bit của SQL Server Compact 3.5 SP1 bằng tệp Windows Installer (MSI) cũng yêu cầu cài đặt phiên bản 32-bit của SQL Server Tệp MSI 3.5 SP1 nhỏ gọn. Đối với các ứng dụng chỉ yêu cầu bản gốc 64-bit, có thể sử dụng triển khai riêng phiên bản 64-bit của SQL Server Compact 3.5 SP1.

Tôi đọc điều này là "bao gồm các tệp SQLCE 32 bit cũng như các tệp 64 bit" nếu phân phối cho máy khách 64 bit.

Làm cho cuộc sống trở nên thú vị, tôi đoán .. phải nói rằng tôi thích dòng "những gì dường như là những vấn đề không liên tục" ... nghe hơi giống như "bạn đang tưởng tượng mọi thứ, nhưng đề phòng, hãy làm điều này ..."


1

Một bản dựng .Net với sự phụ thuộc x86 / x64

Trong khi tất cả các câu trả lời khác cung cấp cho bạn giải pháp để tạo các Bản dựng khác nhau theo nền tảng, tôi cung cấp cho bạn một tùy chọn để chỉ có cấu hình "AnyCPU" và tạo một bản dựng hoạt động với các dlls x86 và x64 của bạn.

Bạn phải viết một số mã đường ống dẫn nước cho việc này.

Độ phân giải của x86 / x64-dlls chính xác trong thời gian chạy

Các bước:

  1. Sử dụng AnyCPU trong csproj
  2. Quyết định xem bạn chỉ tham chiếu x86 hay x64 dlls trong csprojs của mình. Điều chỉnh cài đặt UnitTests cho phù hợp với cài đặt kiến ​​trúc bạn đã chọn. Điều quan trọng là gỡ lỗi / chạy các bài kiểm tra bên trong VisualStudio.
  3. Trên Thuộc tính-Tham chiếu, đặt Sao chép Phiên bản Cục bộ & Cụ thể thành false
  4. Loại bỏ các cảnh báo kiến ​​trúc bằng cách thêm dòng này vào PropertyGroup đầu tiên trong tất cả các tệp csproj của bạn nơi bạn tham chiếu x86 / x64: <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
  5. Thêm tập lệnh postbuild này vào dự án khởi động của bạn, sử dụng và sửa đổi các đường dẫn của tập lệnh này để nó sao chép tất cả các dlls x86 / x64 của bạn trong các thư mục con tương ứng của build 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

    -> Khi bạn bắt đầu ứng dụng ngay bây giờ, bạn nhận được một ngoại lệ là không thể tìm thấy lắp ráp.

  6. Đăng ký sự kiện AssemblyResolve ngay tại đầu điểm nhập đơn của bạn

    AppDomain.CurrentDomain.AssemblyResolve += TryResolveArchitectureDependency;

    với phương pháp này:

    /// <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. Nếu bạn có các bài kiểm tra đơn vị, hãy tạo một TestClass với một Phương pháp có AssemblyInitializeAttribute và cũng đăng ký TryResolveArchitectureDependency-Handler ở trên ở đó. (Điều này đôi khi sẽ không được thực thi nếu bạn chạy các bài kiểm tra đơn lẻ bên trong studio trực quan, các tham chiếu sẽ không được giải quyết từ thùng UnitTest. Do đó, quyết định ở bước 2 rất quan trọng.)

Những lợi ích:

  • Một cài đặt / xây dựng cho cả hai nền tảng

Hạn chế: - Không có lỗi tại thời điểm biên dịch khi x86 / x64 dlls không khớp. - Bạn vẫn nên chạy thử nghiệm ở cả hai chế độ!

Tùy chọn tạo tệp thực thi thứ hai dành riêng cho kiến ​​trúc x64 với Corflags.exe trong tập lệnh postbuild

Các biến thể khác để thử: - Bạn không cần trình xử lý sự kiện AssemblyResolve nếu bạn đảm bảo rằng các tệp tin phù hợp được sao chép vào thư mục nhị phân của bạn khi bắt đầu (Đánh giá kiến ​​trúc Quy trình -> di chuyển các tệp tin tương ứng từ x64 / x86 sang thư mục bin và quay lại). ) - Trong Trình cài đặt, hãy đánh giá kiến ​​trúc và xóa các tệp nhị phân cho cấu trúc sai và di chuyển các tệp đúng vào thư mục bin.


0

Về câu hỏi cuối cùng của bạn. Nhiều khả năng bạn không thể giải quyết điều này trong một MSI duy nhất. Nếu bạn đang sử dụng thư mục đăng ký / hệ thống hoặc bất cứ thứ gì liên quan, bản thân MSI phải biết điều này và bạn phải chuẩn bị MSI 64 bit để cài đặt đúng cách trên máy 32 bit.

Có khả năng bạn có thể cài đặt sản phẩm của mình dưới dạng ứng dụng 32 it và vẫn có thể làm cho nó chạy dưới dạng 64 bit, nhưng tôi nghĩ điều đó có thể hơi khó đạt được.

điều đó đang được nói, tôi nghĩ bạn sẽ có thể giữ một cơ sở mã duy nhất cho mọi thứ. Ở nơi làm việc hiện tại của tôi, chúng tôi đã cố gắng làm như vậy. (nhưng nó đã phải mất một số tung hứng để làm cho mọi thứ chơi với nhau)

Hi vọng điêu nay co ich. Đây là liên kết đến một số thông tin liên quan đến các vấn đề 32/64 bit: http://blog.typemock.com/2008/07/registry-on-windows-64-bit-double-your.html


0

Nếu bạn sử dụng Tác vụ tùy chỉnh được viết bằng .NET như một phần của trình cài đặt MSI thì bạn gặp phải vấn đề khác.

'Shim' chạy các hành động tùy chỉnh này luôn là 32 bit sau đó hành động tùy chỉnh của bạn cũng sẽ chạy 32 bit, bất chấp mục tiêu bạn chỉ định.

Thông tin thêm và một số động tác ninja để di chuyển (về cơ bản thay đổi MSI để sử dụng phiên bản 64 bit của miếng đệm này)

Xây dựng MSI trong Visual Studio 2005/2008 để hoạt động trên SharePoint 64

Hành động tùy chỉnh được quản lý 64-bit với Visual Studio


0

Bạn có thể tạo hai giải pháp khác nhau và hợp nhất chúng sau đó! Tôi đã làm điều này cho VS 2010. và nó hoạt động. Tôi đã có 2 giải pháp khác nhau do CMake tạo ra và tôi đã hợp nhất chúng


0

Bạn có thể sử dụng một điều kiện cho Nhóm mục cho các tham chiếu dll trong tệp dự án.
Điều này sẽ khiến studio trực quan kiểm tra lại điều kiện và tham chiếu bất cứ khi nào bạn thay đổi cấu hình hoạt động.
Chỉ cần thêm một điều kiện cho mỗi cấu hình.

Thí dụ:

 <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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.