我已经建立了一个"Any CPU"的Windows服务,为什么它在我的64位机器上以32位模式运行?

41

我已经构建了一个 "Any CPU" 的 Windows 服务。然而,在我的 64 位机器上运行时,它以 32 位模式运行。如何解决这个问题?我正在使用 .NET 和 C#,我的操作系统是 Windows 2008 R2。

如果我在 x64 上构建它,则可以正确地在 64 位模式下加载。但是,“Any Cpu” - 这就是我想要的 - 在 32 位上加载,即使它所运行的机器完全支持 64 位。

编辑以根据反馈添加更多信息

我们还有第三方工具,并引用了一个 C++ 托管程序集。这些可能或可能不是为任何 CPU 构建的。事实上,我知道 C++ 托管程序集只适用于 x86。但是,奇怪的是,如果我明确指定 x64,该进程将在 x64 中启动并工作。如果框架尝试加载 C++ 托管程序集,则会失败。我不介意这一点,因为在代码中,如果我们在 64 位模式下运行,我们不会加载 32 位托管 ++ 程序集。是否可能是因为构建发现这里有一个 32 位组件,所以应将启动流程(在这种情况下是 Windows 服务程序集)标记为 x86 呢?


2
这是第一次。使用Corflags.exe进行双重检查。 - Hans Passant
你是否有任何仅编译为32位的依赖程序集? - leppie
我只想提一下,这个问题在这里已经讨论过了 http://social.msdn.microsoft.com/Forums/en/netfx64bit/thread/d207eb14-c06b-41de-b553-4a3ab3d53b30 不幸的是,没有提供解决方案。我也遇到了完全相同的问题。 - mr_eko
3
晚来一步,但是这个问题与之前提到的问题不同,不是重复的。 - MatsW
4个回答

20

如果有人遇到和我一样的问题:我创建了两个新配置设置(从Debug配置复制)。由于某种原因,“Prefer32Bit”标志被设置为true,尽管在项目配置页面上该复选框为灰色和未选中

您可以通过直接从.csproj文件中删除该行来修复它。

  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Staging|AnyCPU'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\Staging\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <DebugType>full</DebugType>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <ErrorReport>prompt</ErrorReport>
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
    <Prefer32Bit>true</Prefer32Bit> <!-- REMOVE THIS LINE -->
  </PropertyGroup>

8
您需要将标志设置为“false”-在我的情况下,配置条目不存在,但是VS使用“prefer 32”编译。在VS 2015中有一个“构建”设置来启用/禁用此功能。禁用它会在.csproj中添加一个条目,内容为“<Prefer32Bit>false</Prefer32Bit>”。 - nover
我认为这个标志来自于一些较早版本的Visual Studio。在Visual Studio 2015中,当我在文本编辑器中打开我的*.csproj文件时,我没有看到这个标签Prefer32Bit - RBT

16

有一个设置可以强制将AnyCPU程序集在x64操作系统上作为32位运行。
使用.Net2 x64目录中的ldr64.exe来检查状态:

C:\Windows\Microsoft.NET\Framework64\v2.0.50727>ldr64.exe query
loading kernel32...done.
retrieved GetComPlusPackageInstallStatus entry point
retrieved SetComPlusPackageInstallStatus entry point
当前状态:0x00000001

1-表示“以64位方式运行AnyCPU”
0-表示“以32位方式运行AnyCPU”

尽管我没有在.Net v4文件夹中找到这样的实用程序,但该设置也适用于Net4 AnyCPU程序集。此标志保存在DWORD注册表值Enable64Bit下的键HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework

该设置似乎在系统启动时加载,并且仅更改注册表值不会影响应用程序,直到重新启动。使用ldr64.exe更改标志会立即生效。

请注意,此设置是系统范围的。默认情况下,Enable64Bit设置为1。似乎某些应用程序会将其重置为0,并将其值恢复可能会对该应用程序造成问题。


2
感谢这个答案的帮助。我使用CorFlags将其转换为64位运行。
corflags.exe WindowService.exe /32bitpref- /32bitreq-

我使用的 CorFlags 版本是 4.0.30319.17929,在 C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools 找到的。您可以尝试以下旧版本:

corflags.exe WindowService.exe /32bit-

http://blogs.microsoft.co.il/sasha/2012/04/04/what-anycpu-really-means-as-of-net-45-and-visual-studio-11/ - WhiteKnight

-1

如果启动CLR的应用程序exe被编译为:

  1. x64:使用JIT编译x64版本的程序集时,AnyCPU程序集将变慢。x86程序集将获得BadImageFormatException异常。
  2. x86:AnyCPU程序集会被JIT编译成x86版本。x64程序集将获取BadImageFormatException异常。
  3. AnyCPU:.Net将默认为x86。请参见上文。

我经常使用启动器应用程序,明确地将.exe编译为x64或x86,并提供.x86和.x64版本的.msi。这可能是最简单明了的办法 - 性能收益通常值得管理更多文件的开销。

另外,在安装过程中,您可以使用ngen,它将在安装应用程序时执行所有JIT操作。您将注意到应用程序的启动时间有所改善。

此外,正如我最近在x86应用程序中发现的那样,.net应用程序存在2GB内存限制。即使您的x86拥有4GB RAM并且剩余大量内存,也会出现该情况。


6
根据MSDN文档(http://msdn.microsoft.com/en-us/library/zekwfyz4.aspx):
  • 在64位Windows操作系统上...
  • 使用/platform:anycpu编译的可执行文件将在64位CLR上执行
  • 使用/platform:anycpu编译的DLL将在与加载它的进程相同的CLR上执行。
- PetPaulsen
1
2GB的限制适用于所有32位进程,不仅仅是.NET。使用/LARGEADDRESSAWARE选项链接的应用程序可以使用最多3GB的RAM(或在64位Windows上为4GB)。https://en.wikipedia.org/wiki/3_GB_barrier - phuclv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接