2012-05-21 20 views
9

Tengo un pequeño programa sencillo de línea de comandos, escrito en C#, ejecutándose bajo .NET 4.0 y compilado con Visual Studio 10.0.¿Por qué un .NET EXE, compilado como x86, se ejecuta como x64?

Lo que hace es extraer datos del archivo Access.mdb de otro proveedor e insertarlos en una base de datos del servidor Sql, para que una de nuestras aplicaciones pueda acceder a los datos.

Estamos utilizando las clases OleDbConnection/OleDbCommand/OleDbDataReader de .NET, utilizando Microsoft.Jet.OLEDB.4.0 como el proveedor de datos.

Esto funcionó bien, para nosotros, hasta que intentamos ejecutar en máquinas de 64 bits. Resulta que no hay un proveedor OleDb de 64 bits para .NET. Hay hilos vagos y medio claros sobre el problema diseminados por toda la web, con discusiones sobre diferentes versiones de Access, o MDAC, u Office, o lo que sea, que de alguna manera hizo que las cosas funcionaran para algunas personas.

Lo que hicimos fue configurar el proyecto para apuntar a x86. Y el problema desapareció

Ahora ha vuelto, por razones que simplemente no entiendo. Cuando construyo el programa en mi máquina local, se ejecuta como x86, pero cuando lo construyo en nuestra máquina de compilación, se ejecuta como x64.

El archivo de proyecto está claramente configurado para dirigir X 86:

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

Está construido a partir del mismo archivo batch, ya sea en mi máquina o en la construcción de la máquina:

msbuild OurApp.sln /property:Configuration=Release 

Y los exes generados digamos son x86, independientemente de la máquina en la que están integrados. Si me quedo dumpbin/cabeceras de ambos, veo:

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 

El única diferencia entre los vertederos de un exe construido en mi máquina y un exe construida sobre la máquina de construcción es la marca de tiempo y el camino a la archivo .pdb

Pero, y aquí está lo curioso, un exe integrado en mi máquina funciona bien, uno construido en la máquina de construir se equivoca con el mismo mensaje de error que habíamos visto cuando lo construimos como x64.

Más que eso, nuestro programa obtiene su configuración del registro, y para la comodidad del usuario, si no encuentra una configuración, crea una. Los leemos y creamos en HLM \ SOFTWARE \ OurName \ OurApp. Pero, por supuesto, como se trata de una aplicación de 32 bits que se ejecuta en una máquina de 64 bits, realmente debería leer y escribir desde HLM \ SOFTWARE \ WoW6432Node \ OurName \ OurApp.

Y con las aplicaciones integradas en mi máquina, lo hace. Pero las aplicaciones que están compiladas en la máquina de compilación, a pesar de estar compiladas para x86, y tienen encabezados que indican que deben ejecutarse como x86, leen y escriben desde HLM \ SOFTWARE \ OurName \ OurApp y no desde HLM \ SOFTWARE \ WoW6432Node \ OurName \ OurApp. Como si realmente se ejecutara como una aplicación de 64 bits, a pesar de todo.

¿Alguien tiene alguna idea de cómo podría estar pasando esto?

+1

¿Son idénticos los archivos de configuración? – Oded

+1

Consulte la primera respuesta en http://stackoverflow.com/questions/8794379 para una posible solución. Además, noté que estaba construyendo la configuración 'AnyCPU' que es distinta de' x64' y 'x86' y puede presentar el comportamiento – skarmats

+0

Sin archivo de configuración. Construir directamente fuera del control de la versión. –

Respuesta

5

Bien, esto es simplemente agravante.

Lo que teníamos, en.archivo csproj, fue esto:

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

Es lo que el resultado de tomar la configuración por defecto, y la cambia por objetivo x86.

que eliminan las configuraciones Cualquier CPU, y crearon nuevas configuraciones x86, y tiene:

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

yo hubiera jurado que la GUI me decía que tenía como objetivo x86 tanto en la depuración y en remisión, en la configuración antigua. Y que los ejecutables resultantes se volcaron como x86 y se ejecutaron como x86 en mi máquina. Pero aparentemente me estaba confundiendo acerca de qué versiones del exe se estaban construyendo bajo qué condiciones, porque mirando el .csproj, está claro que no estábamos especificando x86, cuando construimos la versión.

En cualquier caso, con la nueva configuración las versiones se compilan y ejecutan, independientemente de la máquina en la que están compiladas o en las que se ejecutan.

En cualquier caso, lamento haberlo molestado, y gracias por proporcionarme el oído que me permitió ver el problema de la manera correcta.

+0

Es muy fácil olvidarse de seleccionar "Todas las configuraciones" al cambiar una configuración de proyecto que también debería aplicarse a las configuraciones de depuración y liberación. No estoy seguro de que haya una buena solución de usabilidad para eso, ya que no hay forma de que el IDE lo sepa. I * think * Preferiría que el comportamiento del IDE fuera lo contrario de lo que es ahora: que los cambios en la configuración del proyecto se aplicarían a todas las configuraciones a menos que elijas una selección de "Current config only" (creo que la mayor parte de la configuración de mi proyecto) los cambios se aplican a través de las configuraciones). Pero, sinceramente, no estoy muy seguro de si me gustaría algo mejor. –

+3

Esto acaba de estropearse en VS2010, creo que se quedaron sin tiempo para realmente solucionar el problema. El nombre de la plataforma no tiene sentido para los proyectos administrados, solo importa la configuración de la plataforma Project + Properties, Compile, Target. Es un efecto secundario de integrar C++ en el sistema msbuild. Así que sí, es muy posible tener una plataforma de código producir x86 que se ejecute en modo de 64 bits. Cuádruple las probabilidades de tener problemas haciendo que la configuración de la plataforma Target sea dependiente de la configuración. Funciona para Debug, tienes la plataforma Target correcta, no funciona para Release porque olvidaste cambiarla. –

Cuestiones relacionadas