10

我有一个简单的小命令行程序,用 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 位应用程序运行一样,尽管如此。

有谁知道这是怎么发生的?

4

1 回答 1

6

好吧,这只是加重了。

我们在 .csproj 文件中拥有的是:

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

这是采用默认配置并将其更改为目标 x86 的结果。

我删除了 AnyCPU 配置,并创建了新的 x86 配置,并得到:

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

现在我可以发誓,GUI 告诉我我在调试和发布时都针对 x86,在旧配置中。并且生成的可执行文件作为 x86 转储,并在我的机器上作为 x86 运行。但显然我对在什么条件下构建什么版本的 exe 感到困惑,因为查看 .csproj,很明显我们在构建版本时没有指定 x86。

在任何情况下,使用新配置,exe 构建和运行,无论它们构建在什么机器上,或者它们运行在哪台机器上。

无论如何,很抱歉给您带来了困扰,并感谢您提供的耳朵让我以正确的方式看待问题。

于 2012-05-21T22:12:59.213 回答