為什麼編譯為 x86 的 .NET EXE 會以 x64 執行?
我有一個簡單的小命令行程序,用 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 建構和執行,無論它們建構在什麼機器上,或者它們執行在哪台機器上。
無論如何,很抱歉給您帶來困擾,並感謝您提供的耳朵讓我以正確的方式看待問題。