Dot-Net

為什麼編譯為 x86 的 .NET EXE 會以 x64 執行?

  • May 21, 2012

我有一個簡單的小命令行程序,用 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 位應用程序執行一樣,儘管如此。

有誰知道這是怎麼發生的?

好吧,這只是加重了。

我們在 .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 建構和執行,無論它們建構在什麼機器上,或者它們執行在哪台機器上。

無論如何,很抱歉給您帶來困擾,並感謝您提供的耳朵讓我以正確的方式看待問題。

引用自:https://stackoverflow.com/questions/10691472