我有一个简单的小命令行程序,用 C# 编写,在 .NET 4.0 下运行,并用 Visual Studio 10.0 编译。
它的作用是从另一个供应商的 Access.mdb 文件中提取数据,并将其插入到 Sql Server 数据库中,这样我们的一个应用程序就可以访问数据。
我们使用 .NET 的 OleDbConnection/OleDbCommand/OleDbDataReader 类,使用 Microsoft.Jet.OLEDB.4.0 作为数据提供者。
这对我们来说很好,直到我们尝试在 64 位机器上运行。事实证明,.NET 没有 64 位 OleDb 提供程序。网络上散布着关于这个问题的模糊、半清楚的线索,讨论了不同版本的 Access、MDAC、Office 或其他任何东西,它们以某种方式使某些人工作正常。
我们所做的是将项目配置为以 x86 为目标。问题就消失了。
现在它又回来了,原因我根本不明白。当我在本地机器上构建程序时,它以 x86 运行,但是当我在我们的构建机器上构建它时,它以 x64 运行。
项目文件明确配置为针对 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>
它是从同一个批处理文件构建的,无论是在我的机器上还是在构建机器上:
msbuild OurApp.sln /property:Configuration=Release
并且生成的 exe说它们是 x86,无论它们是在哪台机器上构建的。如果我在其中一个上运行 dumpbin /headers,我会看到:
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
在我的机器上构建的 exe 的转储和在构建机器上构建的 exe 的转储之间的唯一区别是时间戳和 .pdb 文件的路径。
但是,奇怪的是,在我的机器上构建的一个 exe 运行得很好,在构建机器上构建的一个 exe 会出现与我们在将其构建为 x64 时看到的相同错误消息。
不仅如此——我们的程序从注册表中获取它的配置,为了方便用户,如果它没有找到一个设置,它会创建一个。我们从 HLM\SOFTWARE\OurName\OurApp 中读取并创建它们。但是,当然,因为这是一个在 64 位机器上运行的 32 位应用程序,它确实应该从 HLM\SOFTWARE\WoW6432Node\OurName\OurApp 读取和写入。
使用我机器上构建的应用程序,它确实如此。但是在构建机器上构建的应用程序,尽管是为 x86 编译的,并且具有指示它们应该作为 x86 运行的标头,从 HLM\SOFTWARE\OurName\OurApp 而不是从 HLM\SOFTWARE\WoW6432Node\读取和写入我们的名字\我们的应用程序。就好像它实际上是作为 64 位应用程序运行一样,尽管如此。
有谁知道这是怎么发生的?