C# 带有Perefer 32位选项的.NET 4.5“任意CPU”:不适用于带有XCopy的32位和64位版本的DLL

C# 带有Perefer 32位选项的.NET 4.5“任意CPU”:不适用于带有XCopy的32位和64位版本的DLL,c#,.net,visual-studio-2012,32bit-64bit,xcopy,C#,.net,Visual Studio 2012,32bit 64bit,Xcopy,当我尝试使用一个嵌入式数据库时,它有32位和64位版本,比如C中的SQLite和SQLServerCE—任何CPU [两者都为其32位和64位版本提供XCOPY部署 检查以下链接:] 我注意到,当我们检查prefer32位时,XCOPY部署不起作用,在这种情况下,procoess不是64位的,而是尝试从x64文件夹加载ddl并崩溃 如果我们取消选中“首选32位”,它将与64位一样工作,并找到正确的DLL 即使我将我的项目设置为x86,它也可以工作,并在x86下找到正确的DDL 为什么偏好32位编

当我尝试使用一个嵌入式数据库时,它有32位和64位版本,比如C中的SQLite和SQLServerCE—任何CPU

[两者都为其32位和64位版本提供XCOPY部署

检查以下链接:]

我注意到,当我们检查prefer32位时,XCOPY部署不起作用,在这种情况下,procoess不是64位的,而是尝试从x64文件夹加载ddl并崩溃

如果我们取消选中“首选32位”,它将与64位一样工作,并找到正确的DLL

即使我将我的项目设置为x86,它也可以工作,并在x86下找到正确的DDL


为什么偏好32位编译选项有这种行为?这是一个bug吗?

首选32位的主要目的是通过“CPU任意”设置更好地支持处理器

因此,“任何CPU 32位首选”和“x86”之间的区别只是:编译为x86的.NET应用程序将无法在ARM Windows系统上运行,但“任何CPU 32位首选”应用程序将成功运行


在x64处理器设置上,此选项基本上与使用x86编译选项相同。

首选32位的主要目的是通过“CPU任意”设置更好地支持处理器

因此,“任何CPU 32位首选”和“x86”之间的区别只是:编译为x86的.NET应用程序将无法在ARM Windows系统上运行,但“任何CPU 32位首选”应用程序将成功运行


在x64处理器上设置此选项与使用x86编译选项基本相同。

我可以确认Hippias Minor的问题-也让我头疼。SQLite由一个托管库组成,该库选择在运行时从x64或x86目录加载哪个本机DLL,即SQLite.Interop.DLL。通过这种方式,它不需要嵌入本机库,因此更具可移植性——相同的xcopy部署可以在不同的体系结构上工作。这也是通常从NuGet安装SQLite的方式

x86与除能够在ARM上运行之外的任何32位CPU的区别在于,第一个CPU将环境变量PROCESSOR_ARCHITECTURE设置为x86,而第二个CPU将其设置为AMD64!这里描述了这个问题:

因此,使用该方法作为启发式的SQLite将尝试加载64位互操作DLL,但由于它实际上是作为32位进程运行的,因此会失败


一个解决方法可能是检查Environment.Is64BitProcess,如果该值为false,则手动将环境变量更改为x86。

我可以确认Hippias Minor的问题-也让我有些头疼。SQLite由一个托管库组成,该库选择在运行时从x64或x86目录加载哪个本机DLL,即SQLite.Interop.DLL。通过这种方式,它不需要嵌入本机库,因此更具可移植性——相同的xcopy部署可以在不同的体系结构上工作。这也是通常从NuGet安装SQLite的方式

if (!Environment.Is64BitProcess
      && Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
          .Equals("AMD64", StringComparison.InvariantCultureIgnoreCase))
{
// Workaround the "Any CPU" w/ "Prefer 32-bit" option from .NET 4.5+
  Environment.SetEnvironmentVariable("PROCESSOR_ARCHITECTURE", "x86");
}
x86与除能够在ARM上运行之外的任何32位CPU的区别在于,第一个CPU将环境变量PROCESSOR_ARCHITECTURE设置为x86,而第二个CPU将其设置为AMD64!这里描述了这个问题:

因此,使用该方法作为启发式的SQLite将尝试加载64位互操作DLL,但由于它实际上是作为32位进程运行的,因此会失败

解决方法可能是检查Environment.Is64BitProcess,如果为false,则手动将环境变量更改为x86

if (!Environment.Is64BitProcess
      && Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE")
          .Equals("AMD64", StringComparison.InvariantCultureIgnoreCase))
{
// Workaround the "Any CPU" w/ "Prefer 32-bit" option from .NET 4.5+
  Environment.SetEnvironmentVariable("PROCESSOR_ARCHITECTURE", "x86");
}
在任何SQLite代码似乎都能使这件事正常工作之前


在任何SQLite代码似乎都能使这件事正常运行之前。

但是,它们在理论上似乎是相等的。那么为什么x86和任何具有首选32位的cpu选项的行为不同呢?在第12步下的第一篇文章中有这样一条信息:您可以忽略这些警告,因为SQL Compact运行时足够智能,可以为安装它的系统选择正确的支持DLL集。如果它是一个bug,那么compact运行时可能关注的是它是如何编译的,而不是它的运行方式。换句话说,仅仅因为它被编译为CPU Any并不意味着它将作为如上所述的64位应用程序运行。没有任何警告。它只是崩溃了。但是,它们在理论上似乎是相等的。那么为什么x86和任何具有首选32位的cpu选项的行为不同呢?在第12步下的第一篇文章中有这样一条消息:您可以忽略这些警告,因为SQL Compact运行时足够智能,可以为安装它的系统选择正确的支持DLL集。如果它是一个bug,那么compact运行时可能关注的是它是如何编译的,而不是它的运行方式。换句话说,仅仅因为它被编译为CPU Any并不意味着它将作为如上所述的64位应用程序运行。没有任何警告。简直太粗鲁了 H