2012-05-21 4 views
9

Ho un semplice programma da riga di comando, scritto in C#, in esecuzione su .NET 4.0 e compilato con Visual Studio 10.0.Perché un EXE .NET, compilato come x86, viene eseguito come x64?

Quello che fa è estrarre i dati dal file Access.mdb di un altro fornitore e inserirli in un database Sql Server, in modo che una delle nostre app possa accedere ai dati.

Utilizziamo le classi OleDbConnection/OleDbCommand/OleDbDataReader di .NET, utilizzando Microsoft.Jet.OLEDB.4.0 come provider di dati.

Questo ha funzionato bene, per noi, fino a quando non abbiamo provato a eseguire su macchine a 64 bit. Risulta che non esiste un provider OleDb a 64 bit per .NET. Ci sono discussioni vaghe e semitrasparenti sul problema sparse per tutto il web, con discussioni su diverse versioni di Access, o MDAC, o Office, o qualsiasi altra cosa, che in qualche modo ha reso le cose funzionanti per alcune persone.

Quello che abbiamo fatto è stato configurare il progetto su target x86. E il problema è andato via.

Ora è tornato, per ragioni che semplicemente non capisco. Quando costruisco il programma sul mio computer locale, viene eseguito come x86, ma quando lo compilo sul nostro computer di costruzione, viene eseguito come x64.

Il file di progetto è chiaramente configurato per x86:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> 
    <DebugType>pdbonly</DebugType> 
    <Optimize>true</Optimize> 
    <OutputPath>bin\Release\</OutputPath> 
    <DefineConstants>TRACE</DefineConstants> 
    <ErrorReport>prompt</ErrorReport> 
    <WarningLevel>4</WarningLevel> 
    <PlatformTarget>x86</PlatformTarget> 
</PropertyGroup> 

E 'costruito dalla stessa batchfile, sia sulla mia macchina o sul sistema di compilazione:

msbuild OurApp.sln /property:Configuration=Release 

E i exes generati dite sono x86, indipendentemente dal computer su cui sono costruiti. Se corro dumpbin/intestazioni su entrambi, vedo:

FILE HEADER VALUES 
     14C machine (x86) 
      3 number of sections 
    4FBA64C8 time date stamp Mon May 21 10:52:40 2012 
      0 file pointer to symbol table 
      0 number of symbols 
      E0 size of optional header 
     102 characteristics 
       Executable 
       32 bit word machine 

L'unica differenza tra le discariche di un exe costruita sulla mia macchina e un exe costruita sul sistema di compilazione è il timestamp e il percorso del file .pdb.

Ma, ed ecco la cosa strana, un exe costruito sulla mia macchina funziona bene, uno costruito sugli errori della macchina di compilazione con lo stesso messaggio di errore che avevamo visto quando lo avevamo creato come x64.

Più di questo - il nostro programma ottiene la sua configurazione dal registro e, per comodità dell'utente, se non trova un'impostazione, ne crea uno. Li leggiamo e li creiamo in, HLM \ SOFTWARE \ OurName \ OurApp. Ma, naturalmente, dal momento che questa è un'app a 32 bit in esecuzione su una macchina a 64 bit, dovrebbe davvero essere la lettura e la scrittura da HLM \ SOFTWARE \ WoW6432Node \ OurName \ OurApp.

E con le app create sulla mia macchina, lo fa. Ma le app che sono costruite sulla macchina di compilazione, nonostante siano compilate per x86 e con intestazioni che indicano che dovrebbero essere eseguite come x86, leggere e scrivere da HLM \ SOFTWARE \ OurName \ OurApp e non da HLM \ SOFTWARE \ WOW6432Node \ OurName \ OurApp. Come se fosse effettivamente in esecuzione come un'app 64-bit, nonostante tutto.

Qualcuno ha idea di come questo potrebbe accadere?

+1

I file di configurazione sono identici? – Oded

+1

Vedere la prima risposta su http://stackoverflow.com/questions/8794379 per una possibile soluzione. Inoltre, ho notato che stavi creando la configurazione di 'AnyCPU' che è distinta da' x64' e 'x86' e potrebbe introdurre il comportamento – skarmats

+0

Nessun file di configurazione. Costruire direttamente dal controllo di versione. –

risposta

5

OK, questo è solo aggravante.

Quello che avevamo avuto, nel.file di csproj, era questo:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> 
    <DebugSymbols>true</DebugSymbols> 
    <DebugType>full</DebugType> 
    <Optimize>false</Optimize> 
    <OutputPath>bin\Debug\</OutputPath> 
    <DefineConstants>DEBUG;TRACE</DefineConstants> 
    <ErrorReport>prompt</ErrorReport> 
    <WarningLevel>4</WarningLevel> 
    <PlatformTarget>x86</PlatformTarget> 
</PropertyGroup> 
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> 
    <DebugType>pdbonly</DebugType> 
    <Optimize>true</Optimize> 
    <OutputPath>bin\Release\</OutputPath> 
    <DefineConstants>TRACE</DefineConstants> 
    <ErrorReport>prompt</ErrorReport> 
    <WarningLevel>4</WarningLevel> 
</PropertyGroup> 

E 'quello che il risultato di prendere la configurazione di default, e cambiando per indirizzare x86.

ho tolto le configurazioni AnyCPU, e ha creato nuove configurazioni x86, e ottenuto:

<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> 
    <DebugSymbols>true</DebugSymbols> 
    <OutputPath>bin\x86\Debug\</OutputPath> 
    <DefineConstants>DEBUG;TRACE</DefineConstants> 
    <DebugType>full</DebugType> 
    <PlatformTarget>x86</PlatformTarget> 
    <ErrorReport>prompt</ErrorReport> 
    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules> 
</PropertyGroup> 
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> 
    <OutputPath>bin\x86\Release\</OutputPath> 
    <DefineConstants>TRACE</DefineConstants> 
    <Optimize>true</Optimize> 
    <DebugType>pdbonly</DebugType> 
    <PlatformTarget>x86</PlatformTarget> 
    <ErrorReport>prompt</ErrorReport> 
    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets> 
    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules> 
</PropertyGroup> 

Ora avrei giurato che l'interfaccia grafica mi stava dicendo che si indirizzava x86 sia in debug e di rilascio, nel vecchia configurazione. E che gli eseguibili risultanti sono stati scaricati come x86 e sono stati eseguiti come x86 sulla mia macchina. Ma apparentemente mi stavo confondendo su quali versioni dell'exe fossero state costruite in quali condizioni, perché guardando il .csproj, è chiaro che non stavamo specificando x86, quando costruimmo il rilascio.

In ogni caso, con la nuova configurazione gli exe compilano ed eseguono, indipendentemente dal computer su cui sono costruiti o su cui vengono eseguiti.

In ogni caso, mi dispiace averti turbato, e grazie per avermi fornito l'orecchio che mi ha permesso di guardare il problema nel modo giusto.

+0

È troppo facile dimenticare di selezionare "Tutte le configurazioni" quando si modifica un'impostazione di progetto che dovrebbe applicare anche le configurazioni di debug e release. Non sono sicuro che ci sia una buona soluzione per l'usabilità, dal momento che non c'è modo per l'IDE di saperlo. I * think * Preferirei che il comportamento dell'IDE fosse l'opposto di quello che è ora - che le modifiche alle impostazioni del progetto si applicassero a tutte le configurazioni a meno che non si scelga una selezione "Current config only" (penso che la maggior parte dell'impostazione del mio progetto le modifiche si applicano attraverso le configurazioni). Ma sinceramente, non sono sicuro se mi piacerebbe tanto. –

+3

Questo è appena stato incasinato in VS2010, penso che abbiano finito il tempo per risolvere davvero il problema. Il nome della piattaforma non ha senso per i progetti gestiti, solo l'impostazione della piattaforma Project + Properties, Compile, Target è importante. È un effetto collaterale dell'integrazione di C++ nel sistema msbuild. Quindi sì, avere una piattaforma di x86 produce codice che gira in modalità a 64 bit è molto possibile. Quadruplicare le probabilità di problemi impostando la piattaforma Target in base alla configurazione. Funziona con Debug, hai la piattaforma Target giusta, non funziona per Release perché hai dimenticato di cambiarlo. –