Targeting sia a 32 bit che a 64 bit con Visual Studio nella stessa soluzione / progetto

Ho un piccolo dilemma su come impostare le build del mio studio visivo per il targeting multiplo.

Background: c # .NET v2.0 con p / invocazione in DLL di 32 bit di terze parti, SQL compatto v3.5 SP1, con un progetto di installazione. Al momento, il target della piattaforma è impostato su x86 in modo che possa essere eseguito su Windows x64.

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

Ciò solleva alcune domande a cui non ho ancora risposto. Voglio avere lo stesso identico codice base. Devo creare con riferimenti al set a 32 bit di DLL a 64 bit o DLL. (Sia di terze parti e SQL Server Compact)

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

Devo creare 2 progetti di installazione separati (std. Progetti di Visual Studio, senza Wix o qualsiasi altra utilità) o possono essere risolti nello stesso .msi?

Eventuali idee e / o raccomandazioni sarebbero ben accetti.

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

  • Riferimenti a assembly gestiti esterni con lo stesso nome ma il loro specifico bitness (questo vale anche per gli assembly di interoperabilità COM)
  • Il pacchetto MSI (che, come è già stato notato, dovrà scegliere come target x86 o x64)
  • Qualsiasi azione personalizzata basata su class di installazione .NET nel pacchetto MSI

Il problema di riferimento all’assembly non può essere risolto interamente in VS.NET, poiché consente di aggiungere un riferimento con un nome specifico a un progetto solo una volta. Per ovviare a questo problema, modifica manualmente il file di progetto (in VS, fai clic con il pulsante destro del mouse sul file di progetto in Esplora soluzioni, seleziona Scarica progetto, quindi fai nuovamente clic con il pulsante destro e seleziona Modifica). Dopo aver aggiunto un riferimento, ad esempio, alla versione x86 di un assembly, il file di progetto conterrà qualcosa come:

 C:\path\to\x86\DLL  

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

  ....  

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

   C:\path\to\x64\DLL   

Dopo aver ricaricato il progetto in VS.NET, la finestra di dialogo Riferimento assemblaggio sarà un po ‘confusa da queste modifiche e potresti riscontrare alcuni avvisi sugli assiemi con il processore di destinazione sbagliato, ma tutte le tue build funzioneranno correttamente.

La soluzione del problema MSI è successiva e, sfortunatamente, ciò richiederà uno strumento non-VS.NET: preferisco l’ Advanced Installer di Caphyon a tale scopo, in quanto elimina il trucco di base (creare un MSI comune, oltre a 32 bit e MSI specifici a 64 bit e utilizzare un launcher di installazione .EXE per estrarre la versione corretta e eseguire le correzioni necessarie in fase di esecuzione) molto, molto bene.

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

Una cosa che potrebbe comunque richiedere WiX, anche se si utilizza Advanced Installer, è per le azioni personalizzate di .NET Installer Class. Sebbene sia banale specificare alcune azioni che dovrebbero essere eseguite solo su determinate piattaforms (utilizzando rispettivamente le condizioni di esecuzione VersionNT64 e NOT VersionNT64), le azioni personalizzate IA integrate verranno eseguite utilizzando il framework a 32 bit, anche su macchine a 64 bit .

Questo problema potrebbe essere risolto in una versione futura, ma per il momento (o quando si utilizza uno strumento diverso per creare i propri MSI con lo stesso problema), è ansible utilizzare il supporto delle azioni personalizzate gestito di WiX 3.0 per creare DLL di azioni con la corretta verrà eseguito utilizzando il Framework corrispondente.


Modifica: dalla versione 8.1.2, Advanced Installer supporta correttamente le azioni personalizzate a 64 bit. Poiché la mia risposta originale, il suo prezzo è aumentato un po ‘, sfortunatamente, anche se è ancora un ottimo valore rispetto a InstallShield e il suo ilk …


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

       

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

Supponiamo di avere le DLL compilate per entrambe le piattaforms e si trovano nel seguente percorso:

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

Devi semplicemente modificare il tuo file .csproj da questo:

 C:\whatever\x86\whatever.dll 

A questa:

 C:\whatever\$(Platform)\whatever.dll 

Dovresti quindi essere in grado di build il tuo progetto su entrambe le piattaforms e MSBuild cercherà nella directory corretta la piattaforma scelta.

Non sono sicuro della risposta totale alla tua domanda, ma ho pensato di segnalare un commento nella sezione Informazioni aggiuntive della pagina di download di SQL Compact 3.5 SP1, vedendo che stai guardando x64 – spero che sia d’aiuto.

A causa delle modifiche apportate a SQL Server Compact SP1 e al supporto aggiuntivo della versione a 64 bit, gli ambienti a installazione centrale e in modalità mista della versione a 32 bit di SQL Server Compact 3.5 e 64 bit di SQL Server Compact 3.5 SP1 possono creare elementi intermittenti i problemi. Per ridurre il potenziale di conflitti e abilitare la distribuzione neutrale della piattaforma delle applicazioni client gestite, l’installazione centralizzata della versione a 64 bit di SQL Server Compact 3.5 SP1 utilizzando il file Windows Installer (MSI) richiede anche l’installazione della versione a 32 bit di SQL Server File MSI Compact 3.5 SP1. Per le applicazioni che richiedono solo 64 bit nativi, è ansible utilizzare la distribuzione privata della versione a 64 bit di SQL Server Compact 3.5 SP1.

Ho letto questo come “include i file SQLCE a 32 bit e i file a 64 bit” se si distribuisce per client a 64 bit.

Rende la vita interessante immagino .. devo dire che amo la frase “ciò che sembra essere problemi intermittenti” … suona un po ‘come “stai immaginando le cose, ma nel caso, fallo …”

Per quanto riguarda la tua ultima domanda. Molto probabilmente non puoi risolvere questo problema all’interno di un singolo MSI. Se si utilizzano cartelle del Registro di sistema / di sistema o qualsiasi cosa correlata, lo stesso MSI deve essere consapevole di ciò ed è necessario preparare un MSI a 64 bit per l’installazione corretta sulla macchina a 32 bit.

Esiste la possibilità che tu possa far sì che il tuo prodotto sia installato come un’applicazione da 32 ed essere ancora in grado di farlo funzionare a 64 bit, ma penso che potrebbe essere piuttosto difficile da ottenere.

Detto questo penso che dovresti essere in grado di mantenere un unico codice base per tutto. Nel mio attuale posto di lavoro siamo riusciti a farlo. (ma ci è voluto un po ‘di giocoleria per far suonare tutto insieme)

Spero che questo ti aiuti. Ecco un link ad alcune informazioni relative ai numeri 32/64 bit: http://blog.typemock.com/2008/07/registry-on-windows-64-bit-double-your.html

Se si utilizzano azioni personalizzate scritte in .NET come parte del programma di installazione MSI, si ha un altro problema.

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

Maggiori informazioni e alcune mosse ninja per spostarsi (in pratica cambia l’MSI per usare la versione a 64 bit di questo shim)

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

Azioni personalizzate gestite a 64 bit con Visual Studio

È ansible generare due soluzioni in modo diverso e unirle in seguito! L’ho fatto per VS 2010. e funziona. Ho avuto 2 diverse soluzioni generate da CMake e le ho unite

È ansible utilizzare una condizione per un ItemGroup per i riferimenti dll nel file di progetto.
Ciò farà sì che lo studio visivo ricontrollare la condizione e i riferimenti ogni volta che si modifica la configurazione triggers.
Basta aggiungere una condizione per ogni configurazione.

Esempio:

    ..\DLLName.dll   {AAAAAA-000000-BBBB-CCCC-TTTTTTTTTT} MyOtherProject   

Una versione .Net con dipendenze x86 / x64

Mentre tutte le altre risposte ti danno una soluzione per creare diverse build in base alla piattaforma, ti do la possibilità di avere solo la configurazione “AnyCPU” e creare una build che funzioni con le tue x86 e x64 DLL.

Devi scrivere del codice idraulico per questo. Non riuscivo a farlo funzionare con app.config. Se qualcun altro conosce un modo per risolverlo tramite app.config mi piacerebbe davvero saperlo.

Risoluzione di x86 / x64-dll corrette in fase di runtime

passi:

  1. Utilizzare AnyCPU in csproj
  2. Decidi se fai riferimento solo alle x86 o alle x64 dll nel tuo csprojs. Adatta le impostazioni di UnitTests alle impostazioni di architettura che hai scelto. È importante per il debug / eseguire i test all’interno di VisualStudio.
  3. Su Riferimento-Proprietà impostare Copia locale e versione specifica su falso
  4. Eliminare gli avvisi di architettura aggiungendo questa linea al primo PropertyGroup in tutti i file csproj in cui si fa riferimento a x86 / x64: None
  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 bin \ x86 \ bin \ x64 \ build

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

    -> Quando avvii l’applicazione ora, ottieni un’eccezione che non è stato ansible trovare nell’assembly.

  6. Registrare l’evento AssemblyResolve direttamente all’inizio del punto di inserimento dell’applicazione

     AppDomain.CurrentDomain.AssemblyResolve += TryResolveArchitectureDependency; 

    con questo metodo:

     ///  /// Event Handler for AppDomain.CurrentDomain.AssemblyResolve ///  /// The app domain /// The resolve event args /// The architecture dependent assembly 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 si dispone di test unitari, creare un TestClass con un metodo che abbia AssemblyInitializeAttribute e registrare anche il TryResolveArchitectureDependency-Handler sopra. (Questo non verrà eseguito a volte se si eseguono test singoli all’interno di Visual Studio, i riferimenti verranno risolti non dal cestino UnitTest. Pertanto la decisione nel passaggio 2 è importante.)

Benefici:

  • Un’installazione / costruzione per entrambe le piattaforms

Svantaggi: – Nessun errore in fase di compilazione quando le DLL x86 / x64 non corrispondono. – Dovresti comunque eseguire il test in entrambe le modalità!

Facoltativamente, crea un secondo eseguibile che è esclusivo per l’architettura x64 con Corflags.exe nello script post-build

Altre varianti da provare: – Non è necessario il gestore di eventi AssemblyResolve se si assicura diversamente che le DLL vengano copiate nella cartella binaria all’avvio (Evaluate Process architecture -> sposta le DLL corrispondenti da x64 / x86 alla cartella bin e viceversa). – In Installer valuta l’architettura ed elimina i binari per l’architettura sbagliata e sposta quelli giusti nella cartella bin.