Domanda

Ho un piccolo dilemma su come impostare i miei build di Visual Studio per il multi-targeting.

Sfondo: c # .NET v2.0 con p / invocazione in DLL a 32 bit di terze parti, SQL compact v3.5 SP1, con un progetto di installazione. Al momento, la destinazione della piattaforma è impostata su x86, quindi può essere eseguita su Windows x64.

La società di terze parti ha appena rilasciato versioni a 64 bit delle loro DLL e voglio creare un programma a 64 bit dedicato.

Ciò solleva alcune domande a cui non ho ancora ricevuto le risposte. Voglio avere la stessa base di codice esatta. Devo costruire con riferimenti al set a 32 bit di DLL o a 64 bit DLL. (Sia di terze parti che SQL Server Compact)

Questo può essere risolto con 2 nuovi set di configurazioni (Debug64 e Release64)?

Devo creare 2 progetti di installazione separati (progetti std. visual studio, nessun Wix o qualsiasi altra utility), o questo può essere risolto all'interno dello stesso .msi?

Eventuali idee e / o raccomandazioni sarebbero benvenute.

È stato utile?

Soluzione

Sì, puoi scegliere come target sia x86 che x64 con la stessa base di codice nello stesso progetto. In generale, le cose funzioneranno solo se crei le giuste configurazioni della soluzione in VS.NET (anche se P / Invoke a DLL completamente non gestite richiederà molto probabilmente un codice condizionale): gli elementi che ho trovato per richiedere particolare attenzione sono:

  • Riferimenti ad assiemi gestiti esterni con lo stesso nome ma con il proprio testimone specifico (questo vale anche per assiemi di interoperabilità COM)
  • Il pacchetto MSI (che, come è già stato notato, dovrà avere come target x86 o x64)
  • Eventuali azioni personalizzate basate sulla classe Installer .NET nel pacchetto MSI

Il problema di riferimento dell'assembly non può essere risolto interamente all'interno di VS.NET, poiché consentirà di aggiungere un riferimento con un determinato nome a un progetto una sola volta. Per ovviare a questo, modificare manualmente il file di progetto (in VS, fare clic con il pulsante destro del mouse sul file di progetto in Esplora soluzioni, selezionare Scarica progetto, quindi fare nuovamente clic con il pulsante destro del mouse e selezionare Modifica). Dopo aver aggiunto un riferimento, diciamo, alla versione x86 di un assembly, il tuo file di progetto conterrà qualcosa del tipo:

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

Avvolgi quel tag di riferimento all'interno di un tag ItemGroup che indica la configurazione della soluzione a cui si applica, ad esempio:

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

Quindi, copia e incolla l'intero tag ItemGroup e modificalo per contenere i dettagli della tua DLL a 64 bit, ad es .:

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

Dopo aver ricaricato il progetto in VS.NET, la finestra di dialogo di riferimento degli assiemi sarà un po 'confusa da queste modifiche e potresti riscontrare alcuni avvertimenti sugli assiemi con il processore di destinazione sbagliato, ma tutte le tue build funzioneranno bene.

La risoluzione del problema MSI è la prossima, e sfortunatamente questo richiederà uno strumento non-VS.NET: preferisco Caphyon Advanced Installer a tale scopo, in quanto risolve il trucco di base in questione (crea un MSI comune, nonché MSI specifici a 32 e 64 bit e usa un launcher di installazione .EXE per estrarre la versione giusta e fare le correzioni richieste in fase di esecuzione) molto, molto bene.

Probabilmente puoi ottenere gli stessi risultati utilizzando altri strumenti o il set di strumenti XML (WiX) di Windows Installer , ma Advanced Installer rende le cose così facili (ed è abbastanza abbordabile) che non ho mai veramente guardato le alternative.

Una cosa per cui potresti comunque richiedere WiX, anche quando si utilizza Advanced Installer, è per le azioni personalizzate della classe .NET Installer. Sebbene sia banale specificare determinate azioni che dovrebbero essere eseguite solo su determinate piattaforme (utilizzando rispettivamente le condizioni di esecuzione VersionNT64 e NOT VersionNT64), le azioni personalizzate AI integrate verranno eseguite utilizzando il Framework a 32 bit, anche su macchine a 64 bit .

Ciò potrebbe essere risolto in una versione futura, ma per ora (o quando si utilizza uno strumento diverso per creare i propri MSI che presentano lo stesso problema), è possibile utilizzare il supporto dell'azione personalizzata gestita di WiX 3.0 per creare DLL di azioni con il testimone adeguato che verrà eseguito usando il Framework corrispondente.


Modifica: dalla versione 8.1.2, Advanced Installer supporta correttamente le azioni personalizzate a 64 bit. Dalla mia risposta originale, il suo prezzo è aumentato un po ', sfortunatamente, anche se è ancora un ottimo rapporto rispetto a InstallShield e ai suoi simili ...


Modifica: se le tue DLL sono registrate nel GAC, puoi anche usare i tag di riferimento standard in questo modo (SQLite come esempio):

<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>

La condizione è inoltre ridotta a tutti i tipi di build, release o debug e specifica solo l'architettura del processore.

Altri suggerimenti

Supponiamo che le DLL siano compilate per entrambe le piattaforme e che si trovino nella seguente posizione:

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

Devi semplicemente modificare il tuo file .csproj da questo:

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

A questo:

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

Dovresti quindi essere in grado di costruire il tuo progetto indirizzato a entrambe le piattaforme e MSBuild cercherà nella directory corretta per la piattaforma scelta.

Non sono sicuro della risposta totale alla tua domanda, ma ho pensato di sottolineare un commento nella sezione Informazioni aggiuntive di pagina di download di SQL Compact 3.5 SP1 vedendo che stai guardando x64 - spero che ti aiuti.

  

A causa di modifiche in SQL Server Compact   SP1 e versione aggiuntiva a 64 bit   supporto, installato centralmente e misto   ambienti in modalità versione a 32 bit di   SQL Server Compact 3.5 e 64 bit   versione di SQL Server Compact 3.5 SP1   può creare ciò che sembra essere   problemi intermittenti. Per ridurre al minimo il   potenziale per conflitti e per consentire   distribuzione neutrale della piattaforma di gestito   applicazioni client, a livello centrale   installazione della versione a 64 bit di SQL   Server Compact 3.5 SP1 utilizzando il   File di Windows Installer (MSI) anche   richiede l'installazione della versione a 32 bit   di MSI di SQL Server Compact 3.5 SP1   file. Solo per applicazioni   richiede 64 bit nativo, privato   distribuzione della versione a 64 bit di   SQL Server Compact 3.5 SP1 può essere   utilizzato.

Ho letto questo come " includo i file SQLCE a 32 bit nonché i file a 64 bit " se si distribuisce per client a 64 bit.

Credo che la vita sia interessante .. devo dire che adoro il " quelli che sembrano essere problemi intermittenti " linea ... suona un po 'come " stai immaginando cose, ma per ogni evenienza, fallo ... "

Per quanto riguarda la tua ultima domanda. Molto probabilmente non puoi risolverlo all'interno di un singolo MSI. Se si utilizzano cartelle di registro / di sistema o qualsiasi altra cosa correlata, lo stesso MSI deve essere consapevole di ciò ed è necessario preparare un MSI a 64 bit da installare correttamente su un computer a 32 bit.

Esiste la possibilità che tu possa installare il tuo prodotto come applicazione 32 it ed essere ancora in grado di farlo funzionare come 64 bit uno, ma penso che potrebbe essere un po 'difficile da raggiungere.

detto questo, penso che dovresti essere in grado di mantenere una sola base di codice per tutto. Nel mio attuale posto di lavoro siamo riusciti a farlo. (ma ci sono voluti alcuni giocoleria per far suonare tutto insieme)

Spero che questo aiuti. Ecco un link ad alcune informazioni relative a problemi a 32/64 bit: http: //blog.typemock. com / 2008/07 / registro-on-Windows-64-bit-double-your.html

Se usi le azioni personalizzate scritte in .NET come parte del tuo programma di installazione MSI, allora hai un altro problema.

Lo 'shim' che esegue queste azioni personalizzate è sempre a 32 bit, quindi anche l'azione personalizzata verrà eseguita a 32 bit, nonostante il target specificato.

Ulteriori informazioni & amp; alcune mosse ninja per aggirare (sostanzialmente cambiare l'MSI per usare la versione a 64 bit di questo shim)

Creazione di un MSI in Visual Studio 2005/2008 per lavorare su un SharePoint 64

Azioni personalizzate gestite a 64 bit con Visual Studio

Puoi generare due soluzioni in modo diverso e unirle successivamente! L'ho fatto per VS 2010. e funziona. Ho avuto 2 diverse soluzioni generate da CMake e le ho unite

Puoi utilizzare una condizione per un gruppo di elementi per i riferimenti dll nel file di progetto.
Ciò farà sì che Visual Studio ricontrollerà la condizione e i riferimenti ogni volta che cambi la configurazione attiva.
Aggiungi una condizione per ogni configurazione.

Esempio:

 <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>

Una build .Net con dipendenze x86 / x64

Mentre tutte le altre risposte ti danno una soluzione per creare build diverse in base alla piattaforma, ti do un'opzione per avere solo il " AnyCPU " configurazione e crea una build che funzioni con le tue dll x86 e x64.

Devi scrivere del codice idraulico per questo. Non sono riuscito a farlo funzionare con app.config. Se qualcun altro conosce un modo per risolverlo tramite app.config, vorrei davvero saperlo.

Risoluzione della corretta x86 / x64-dlls in fase di esecuzione

Passi:

  1. Usa AnyCPU in csproj
  2. Decidi se fai riferimento solo alle dll x86 o x64 nei tuoi csprojs. Adatta le impostazioni di UnitTest alle impostazioni dell'architettura che hai scelto. È importante per il debug / esecuzione dei test all'interno di VisualStudio.
  3. Su Riferimento-Proprietà impostare Copia locale & amp; Versione specifica su false
  4. Elimina gli avvisi di architettura aggiungendo questa riga al primo gruppo di proprietà in tutti i tuoi file csproj dove fai riferimento a x86 / x64: <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
  5. Aggiungi questo script postbuild al tuo progetto di avvio, usa e modifica i percorsi di questo script sp che copia tutte le tue dll x86 / x64 nelle corrispondenti sottocartelle del tuo cestino di compilazione \ 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

    - GT &; Quando avvii l'applicazione adesso, ricevi un'eccezione che non è stato possibile trovare l'assemblea.

  6. Registra l'evento AssemblyResolve proprio all'inizio del punto di ingresso dell'applicazione

    AppDomain.CurrentDomain.AssemblyResolve += TryResolveArchitectureDependency;
    

    con questo metodo:

    /// <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. Se disponi di unit test, crea una TestClass con un metodo che ha un AssemblyInitializeAttribute e lì registra anche il precedente TryResolveArchitectureDependency-Handler. (Questo non verrà eseguito a volte se si eseguono test singoli all'interno di Visual Studio, i riferimenti non verranno risolti dal cestino UnitTest. Pertanto, la decisione nel passaggio 2 è importante.)

I vantaggi:

  • Una installazione / Build per entrambe le piattaforme

Svantaggi:  - Nessun errore al momento della compilazione quando le dll x86 / x64 non corrispondono.  - Dovresti comunque eseguire il test in entrambe le modalità!

Facoltativamente, creare un secondo eseguibile esclusivo per l'architettura x64 con Corflags.exe nello script postbuild

Altre varianti da provare:  - Non sarà necessario il gestore eventi AssemblyResolve se si assicura altrimenti che le DLL vengano copiate nella cartella binaria all'avvio (Valuta l'architettura del processo - & GT; sposta le corrispondenti DLL da x64 / x86 nella cartella bin e viceversa).  - In Installer valuta l'architettura ed elimina i file binari per l'architettura errata e sposta quelli giusti nella cartella bin.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top