동일한 솔루션/프로젝트에서 Visual Studio를 사용하여 32 비트와 64 비트를 모두 타겟팅

StackOverflow https://stackoverflow.com/questions/145803

문제

멀티 타겟팅을위한 Visual Studio 빌드를 설정하는 방법에 대해 약간의 딜레마가 있습니다.

배경 : C# .NET v2.0 P/가 3 파티 32 비트 DLL로 호출, SQL Compact v3.5 SP1, 설정 프로젝트. 현재 플랫폼 대상은 X86으로 설정되어 Windows X64에서 실행할 수 있습니다.

제 3 자 회사는 방금 64 비트 버전의 DLL을 출시했으며 전용 64 비트 프로그램을 구축하고 싶습니다.

이것은 아직 답을 얻지 못한 몇 가지 질문을 제기합니다. 정확히 동일한 코드 기반을 갖고 싶습니다. DLL의 32 비트 세트 또는 64 비트 DLL에 대한 참조로 구축해야합니다. (타사 및 SQL Server Compact)

이것은 2 개의 새로운 구성 세트 (Debug64 및 Release64)로 해결할 수 있습니까?

2 개의 개별 설정 프로젝트 (STD. Visual Studio Projects, WIX 또는 기타 유틸리티 없음)를 만들어야합니까, 아니면 동일한 .MSI 내에서 해결할 수 있습니까?

모든 아이디어 및/또는 권장 사항을 환영합니다.

도움이 되었습니까?

해결책

예, 동일한 프로젝트에서 동일한 코드 기반으로 X86과 X64를 모두 타겟팅 할 수 있습니다. 일반적으로 vs.net에서 올바른 솔루션 구성을 만들면 상황이 작동합니다 (P/는 완전히 관리되지 않은 DLL으로 호출하지만 조건부 코드가 필요할 가능성이 높습니다) : 특별한주의가 필요한 항목은 다음과 같습니다.

  • 동일한 이름을 가진 외부 관리 어셈블리에 대한 참조 자체의 특정 비트 (COM Interop 어셈블리에도 적용됨)
  • MSI 패키지 (이미 언급 된 바와 같이 x86 또는 x64를 대상으로해야합니다).
  • MSI 패키지의 모든 Custom .NET Installer 클래스 기반 작업

어셈블리 참조 문제는 vs.net 내에서 완전히 해결할 수 없으므로 프로젝트에 주어진 이름의 참조를 한 번만 추가 할 수 있습니다. 이 문제를 해결하려면 프로젝트 파일을 수동으로 편집하십시오 (VS에서 Solution Explorer에서 프로젝트 파일을 마우스 오른쪽 버튼으로 클릭하고 프로젝트 언로드를 선택한 다음 다시 클릭 한 다음 편집을 선택하십시오). 예를 들어, 어셈블리의 x86 버전에 대한 참조를 추가 한 후 프로젝트 파일은 다음과 같은 내용이 포함됩니다.

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

해당 참조 태그를 항목 그룹 태그 안에 랩핑하여 적용되는 솔루션 구성을 나타냅니다.

<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
   <Reference ...>....</Reference>
</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 도구가 필요합니다. Caphyon을 선호합니다 고급 설치 프로그램 이를 위해, 관련된 기본 트릭을 벗어나면서 (32 비트 및 64 비트 특정 MSI뿐만 아니라 공통 MSI를 만들고, .Exe 설정 런처를 사용하여 올바른 버전을 추출하고 런타임에 필요한 수정을 수행하십시오. ) 아주, 아주 잘.

다른 도구 또는 Windows Installer XML (WIX) 도구 세트, 그러나 고급 설치 프로그램은 대안을 결코 보지 못했기 때문에 일을 쉽게 만들어서 (그에 상당히 저렴합니다).

당신이 한 가지 5월 고급 설치 프로그램을 사용하는 경우에도 여전히 Wix가 필요합니다. 특정 플랫폼에서만 실행 해야하는 특정 조치를 지정하는 것은 사소한 일이지만 (각각 버전에서 versionnt64 실행 조건이 아닌 versionnt64를 사용하여) 내장 AI 사용자 정의 작업은 64 비트 머신에서도 32 비트 프레임 워크를 사용하여 실행됩니다. .

이것은 향후 릴리스에서 고정 될 수 있지만 지금은 다른 도구를 사용하여 동일한 문제가있는 MSI를 만들 때) Wix 3.0의 관리 사용자 지정 조치 지원을 사용하여 적절한 비트가있는 액션 DLL을 생성 할 수 있습니다. 해당 프레임 워크를 사용하여 실행됩니다.


편집 : 버전 8.1.2 기준으로 Advanced Installer는 64 비트 사용자 정의 작업을 올바르게 지원합니다. 나의 원래 대답 이후, 불행히도, 그 가격은 Installshield와 그 ilk와 비교할 때 여전히 매우 좋은 가치이지만, 그 가격은 상당히 증가했습니다 ...


편집 : 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>

조건은 또한 모든 빌드 유형, 릴리스 또는 디버그로 줄어들고 프로세서 아키텍처 만 지정합니다.

다른 팁

두 플랫폼 모두에 대한 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는 선택한 플랫폼의 올바른 디렉토리를 살펴 봅니다.

귀하의 질문에 대한 총 답변은 확실하지 않지만 추가 정보 섹션에서 의견을 지적 할 것이라고 생각했습니다. 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 비트 버전 지원으로 인해 간헐적으로 보일 수 있습니다. 문제. 충돌 가능성을 최소화하고 플랫폼 플랫폼 중립 클라이언트 애플리케이션의 중립 배포를 가능하게하려면 64 비트 버전의 SQL Server Compact 3.5 SP1을 사용하여 Windows Installer (MSI) 파일을 중앙에 설치하려면 32 비트 버전의 SQL Server를 설치해야합니다. 소형 3.5 SP1 MSI 파일. 64 비트 버전의 SQL Server Compact 3.5 SP1의 민간 배포 만 사용하는 기본 64 비트 만 필요한 애플리케이션의 경우 사용할 수 있습니다.

나는 이것을 "32 비트 SQLCE 파일 포함"로 읽습니다. 만큼 잘 64 비트 파일 "64 비트 클라이언트에 배포하는 경우.

인생을 흥미롭게 만듭니다. 나는 "간헐적 인 문제인 것 같다"라인을 좋아한다고 말해야합니다. 라인은 ... "당신은 물건을 상상하고 있지만 경우에 따라 ..."

마지막 질문에 대해. 아마도 당신은 이것을 단일 MSI 내에서 해결할 수 없을 것입니다. 레지스트리/시스템 폴더 또는 관련 제품을 사용하는 경우 MSI 자체가이를 알고 있어야하며 32 비트 머신에 올바르게 설치할 수 있도록 64 비트 MSI를 준비해야합니다.

제품을 32 IT 애플리케이션으로 설치하고 여전히 64 비트로 실행할 수있게 만들 수 있지만 달성하기가 어려울 수 있다고 생각합니다.

즉, 나는 당신이 모든 것에 대한 단일 코드 기반을 유지할 수 있어야한다고 생각합니다. 내 현재 직장에서 우리는 그렇게했습니다. (하지만 모든 것이 함께 플레이하기 위해 저글링이 필요했습니다)

도움이 되었기를 바랍니다. 그녀는 32/64 비트 문제와 관련된 일부 정보에 대한 링크입니다.http://blog.typemock.com/2008/07/registry-on-windows-64-bit-double-your.html

MSI 설치 프로그램의 일부로 .NET에 작성된 사용자 정의 작업을 사용하는 경우 다른 문제가 있습니다.

이러한 사용자 정의 작업을 실행하는 'Shim'은 항상 32 비트입니다. 그러면 사용자 지정 대상에도 불구하고 사용자 정의 작업도 32 비트를 실행합니다.

더 많은 정보 및 일부 닌자가 돌아 다니기 위해 움직입니다 (기본적으로 MSI를 변경 하여이 심의 64 비트 버전을 사용합니다)

SharePoint 64에서 작업하기 위해 Visual Studio 2005/2008에서 MSI 구축

Visual Studio를 사용하여 64 비트 관리 사용자 정의 액션

두 가지 솔루션을 다르게 생성하고 나중에 병합 할 수 있습니다! 나는 vs 2010을 위해 이것을했다. 그리고 그것은 작동한다. Cmake에 의해 생성 된 2 개의 다른 솔루션이 있었고 합병했습니다.

조건을 사용할 수 있습니다 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>

x86/x64 종속성을 갖춘 .NET 빌드 하나입니다

다른 모든 답변은 플랫폼에 따라 다른 빌드를 만들 수있는 솔루션을 제공하지만 "anyCPU"구성 만 가지고 X86 및 X64 DLL과 함께 작동하는 빌드를 만들 수있는 옵션을 제공합니다.

이를 위해 배관 코드를 작성해야합니다. 나는 이것을 app.config와 함께 일할 수 없었다. 다른 사람이 app.config를 통해 그것을 해결하는 방법을 알고 있다면 정말 알고 싶습니다.

런타임에 올바른 x86/x64-dll의 해상도

단계 :

  1. CSPROJ에서 anycpu를 사용하십시오
  2. CSPROJ에서 X86 또는 X64 DLL 만 참조하는지 결정하십시오. UnitTests 설정을 선택한 아키텍처 설정에 적응하십시오. VisualStudio 내에서 테스트를 디버깅/실행하는 것이 중요합니다.
  3. 참조-장점 세트에서 로컬 복사 & 특정 버전 에게 거짓
  4. 이 줄을 첫 번째 라인에 추가하여 아키텍처 경고를 제거하십시오. 속성 그룹 x86/x64를 참조하는 모든 CSPROJ 파일에서 :<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
  5. 이 사후 빌드 스크립트를 시작 프로젝트에 추가 하고이 스크립트 SP의 경로를 사용하고 수정하여 빌드 bin x86 bin x64 의 해당 하위 폴더에서 모든 x86/x64 dlls를 복사합니다.

    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. 단위 테스트가있는 경우 AssemblyInitializeattribute가있는 메소드와 함께 테스트 클래스를 만들고 위의 TryResolVearchiteCturedEction handleder를 등록하십시오. (Visual Studio 내에서 단일 테스트를 실행하는 경우 때때로 실행되지 않으면 참조는 UnitTest Bin에서 해결되지 않으므로 2 단계의 결정이 중요합니다.)

이익:

  • 두 플랫폼 모두에 대한 하나의 설치/빌드

단점 : - x86/x64 dlls가 일치하지 않는 컴파일 시간에 오류가 없습니다. - 여전히 두 모드에서 테스트를 실행해야합니다!

선택적으로 Buflags.exe를 사용하여 x64 아키텍처에 독점적 인 두 번째 실행 파일을 생성합니다.

시험해 볼 다른 변형 : - 어셈블리 폴트 이벤트 핸들러가 필요하지 않습니다. 그렇지 않으면 DLL이 시작시 이진 폴더에 복사되는지 확인하는 경우 (프로세스 아키텍처 평가 -> 해당 DLL을 x64/x86에서 빈 폴더로 이동하십시오.) - 설치 프로그램에서는 잘못된 아키텍처를 위해 아키텍처를 평가하고 바이너리를 삭제하고 올바른 것들을 빈 폴더로 옮깁니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top