为什么 64 位 Windows 需要单独的“Program Files (x86)”文件夹?

Ste*_*ngs 180 windows 64-bit

我知道在 64 位版本的 Windows 上,“Program Files”文件夹用于 64 位程序,“Program Files (x86)”文件夹用于 32 位程序,但为什么这甚至是必要的?

我所说的“必要”并不是指“为什么微软不能做出任何其他设计决定?” 因为他们当然可以。相反,我的意思是,“为什么鉴于 64 位 Windows 的当前设计,32 位程序必须有一个与 64 位程序不同的顶级文件夹?” 换句话说,“如果我以某种方式避免重定向机制并强制所有内容都安装到真实的,会出现C:\Program Files\什么问题?”

有很多关于超级用户和其他地方的问题断言“一个用于 32 位程序,一个用于 64 位程序”,但我找不到任何原因。根据我的经验,32 位程序是否安装在正确的位置似乎并不重要。

Windows 是否以某种方式以不同的方式呈现出“Program Files (x86)”不足的程序?是否有说明确切显示安装在“Program Files (x86)”而不是“Program Files”中的程序有何不同?我认为微软不太可能在没有合法技术原因的情况下引入一个新文件夹。

Dav*_*rtz 93

简短回答:确保遗留的 32 位应用程序继续以与过去相同的方式工作,而不会对 64 位应用程序强加丑陋的规则,这会造成永久性混乱。

这不是必要的。它比其他可能的解决方案更方便,例如要求每个应用程序创建自己的方式来将 32 位 DLL 和可执行文件与 64 位 DLL 和可执行文件分开。

主要原因是使甚至不知道 64 位系统存在的 32 位应用程序“正常工作”,即使 64 位 DLL 安装在应用程序可能看起来的位置。32 位应用程序将无法加载 64 位 DLL,因此需要一种方法来确保 32 位应用程序(可能早于 64 位系统,因此不知道 64 位文件即使存在)也找不到 64 位 DLL,尝试加载它,失败,然后生成错误消息。

对此最简单的解决方案是始终分开的目录。实际上唯一的替代方法是要求每个 64 位应用程序将其可执行文件“隐藏”在 32 位应用程序看不到的地方,例如bin64该应用程序内的目录。但这会给 64 位系统带来永久的丑陋,只是为了支持遗留应用程序。

  • 他们不必跳过这些障碍就可以在同一系统上运行 32 位和 16 位程序。我不记得曾经看到过“ProgramFiles (16)”之类的。此外,32 位程序究竟如何“找到 64 位 DLL 并尝试加载它”?哪些程序会在“%programfiles%”中寻找随机 DLL?如果是共享DLL,则进入WinSxS;如果不共享,则由程序员来管理他们自己的 DLL。这样做的部分是为了程序员的方便而合理的。 (52认同)
  • IIRC Win3.1 没有程序文件目录(或大多数应用程序忽略它);因此,不会有任何遗留的 win16 应用程序开始寻找程序文件中的内容。相反,IIRC 共享库经常被放在 windows 文件夹本身的某个地方。具有 windows\system 和 windows\system32 的 Win32 是其中的产物。 (30认同)
  • @Jarrod:实际上,正如每个开发人员都知道的那样,Microsoft 高度重视向后兼容性*。实际上,他们拥有的每个 API 都有他们拒绝删除的遗留方法,而且他们经常拒绝修复*严重的*错误,因为他们害怕破坏为该 API 编写的旧程序。大多数 API 也是如此,但不适用于 Microsoft 现有的 API。 (24认同)
  • Windows 3.1 不支持长文件名,因此它无法拥有“程序文件”文件夹。 (15认同)
  • @JarrodRoberson:恰恰相反,这是因为 Microsoft 非常重视向后兼容性。 (14认同)
  • @David Schwartz 你是反过来的。32 位应用程序文件夹是重命名的文件夹。这仍然允许从 Program Files 文件夹中意外加载 64 位,该文件夹现在包含 64 位应用程序。此外,该问题与 SysWOW64 和其他内部 ./Windows/... 文件夹重命名或重新映射(或注册表重命名/重新映射)无关。 (3认同)
  • @BlueRaja 我认为 MS 完全正确地向后兼容;消费者,如果他们不得不重新购买他们的所有软件(或为不再生产的东西寻找替代品)不妨转移到另一个平台。兼容性确保对他们已经拥有的软件的投资是有价值的,而不是仅仅因为发布了新版本的 Windows 而变得毫无价值。人们希望事情“正常工作”,如果您不断破坏向后兼容性,您将如何做到这一点? (3认同)
  • @Synetech:我说的是早于(或不使用)WinSxS 的程序。至于“哪些程序会在 %programfiles% 中寻找随机 DLL”,很多人都会这样做。如果您不相信我,请转到 CMD 提示符,执行 `cd %programfiles%\common files`,然后执行 `dir /w/s *.dll`。 (2认同)
  • @Tiberiu-IonuțStan:超出这个问题范围的特殊解决方法用于这些应用程序——更多的是微软对向后兼容性的疯狂投入。 (2认同)
  • @Andy:我认为您将 API 的向后兼容性与编译程序的向后兼容性混淆了。例如,在 .Net 中,为 .Net 2 编译的程序无论如何只能在 .Net 2 运行时中运行,因此升级 Windows 或 .Net 不会以任何方式影响用户,因为它们必须同时具有旧版本和新版本的安装了 .Net 运行时。可能受到影响的是代码本身——微软可以修复一些严重的错误,代价是一些程序不再编译*(然后需要修复以便在较新的运行时编译)*。(续) (2认同)
  • (续)但是,他们不这样做,因为他们不希望现有代码必须在版本之间进行更改,从而导致每个人都会遇到的巨大错误,恕我直言,这对我们开发人员来说比不得不更改更糟糕,更耗时修复版本之间的非编译代码。运行相同 .dll 的不同版本的本机程序也会出现同样的问题。 (2认同)

Der*_*ler 68

它允许您安装 32 位和 64 位版本的应用程序,而不会覆盖自身。


第二天看了这个答案和评论后,我意识到我的答案可能存在重大疏忽。我错误地假设了编程背景,当我在评论中谈论时,我不是指用户,而是程序员。

我不为 Microsoft 工作,我不知道这些文件夹背后的真正原因是什么,但我认为拥有这些文件夹的原因非常明显,我没有任何争论的问题。

所以让我们分解它!

  1. 文件夹很棒!

    让我们就一些事情达成一致。文件夹很棒!我们不需要它们,我们有足够多的可能文件名来将每个文件放在硬盘驱动器的根目录上,那么为什么还要有文件夹呢?

    嗯,他们帮助我们订购我们的东西。订购东西很棒。它可以帮助我们更轻松地处理事情。这在使用需要结构的机器时特别有用。

  2. 分离数据和逻辑很棒!

    编程中常见的一种范式是将数据与逻辑分开。你想那一部分知道如何做一些事情,你想另一部分,你可以做什么

    这也可以在文件系统中找到。

    我们有应用程序(逻辑)文件夹和贵重物品(数据)文件夹:

    逻辑

    • %WINDIR%
    • %PROGRAMFILES%
    • %PROGRAMFILES(x86)%

    数据

    • %PROGRAMDATA%
    • %HOMEDRIVE%%HOMEPATH%

    所以,看起来文件夹很棒,把程序放在他们自己的小文件夹中是有意义的。但为什么有 2 个?为什么不让安装程序处理并将所有内容放在一个Programs文件夹中?

  3. 安装程序不是魔术

    今天,我们经常使用小程序来安装我们的大程序。我们称这些小程序安装程序

    安装程序不是魔术。它们必须由程序员编写,并且是与任何其他应用程序一样的应用程序(可能存在错误)。因此,让我们看看情况假想程序员将不得不面对没有当前系统:

    1 程序文件文件夹

    开发人员维护 2 个安装程序。一种用于 32 位,另一种用于 64 位版本的应用程序。32 位安装程序将写入C:\Program Files\App\64 位安装程序将写入C:\Program Files\App\sixtyfour\.

    2 程序文件文件夹

    开发人员维护 1 个安装程序。安装程序将永远写入%PROGRAMFILES%和依赖于操作系统相应扩大的路径(你其实并不使用环境变量对于这些情况,你会使用SHGetKnownFolderPathFOLDERID_ProgramFiles检索正确的路径)。
    一切都会自动找到它的位置,并且模式与您安装的每个应用程序相同

  4. 一致性有意义

    当你学到一些东西时,这通常意味着观察到的行为是一致的。否则真的没有什么可观察和学习的。

    我们的小文件系统也是如此。始终将相同的内容放入相同的文件夹是有意义的。这样,当我们在寻找东西时,我们就会知道去哪里找。

    32/64 应用程序区分系统进一步实现了这一目标。应用程序被分成 2 个位置以避免名称冲突、二进制加载行为和安全性(在某种程度上)。

我还是不明白。这似乎没用

你永远不应该忘记一件事。人真是愚蠢得不得了。这包括用户、超级用户,尤其是程序员。

这就是为什么我们需要文件系统重定向之类的东西来使我们的系统可用。

程序员只会进入那里并尝试加载C:\Windows\system32\awesome.dll而不关心他们是在 32 位还是 64 位系统上运行。他们会尝试加载 64 位 DLL 并简单地崩溃。一些程序员想使用一些Office DLL,没问题,他们知道在哪里可以找到它!C:\Program Files\Microsoft\Office\14.0\wizards.dll......又一次崩溃!

32 位应用程序的所有这些请求都被重定向到 32 位对应项,以避免应用程序崩溃。

我们需要一些固定的文件夹名称来构建这样一个系统。如果没有支持这种重定向的文件夹结构,那么您将如何使其工作?

好的,现在我明白了。但是为什么不使用C:\Program Files\x86\呢?

现在我们开始哲学了……

如果我以某种方式避免重定向机制并强制所有内容都安装到真实的,会出现C:\Program Files\什么问题?

很可能什么都没有(只要其他应用程序不依赖于该应用程序的固定位置)。

WOW64机构钩入CreateProcess和将执行更复杂的(不是检查可执行文件的文件夹的名称更复杂的)检查可执行图像上以确定它是否是32或64位。

是的,但我的意思是,所有应用程序!

  • 如果我把会发生什么,这两个柴油机和气体进入我的车?
  • 如果我尝试使用会发生什么,在同一行交直流?
  • 如果我继续会发生什么,我的猫,我的鱼在鱼缸一样?

有些问题不需要答案。不打算做,不要做。在这里没有什么可得到的。这种变化可能导致的问题数量总是超过某人在这方面可能看到的任何可能的好处。

  • @Synetech:首先为什么要安装到 `%PROGRAMFILES%` 中?为什么不把用户桌面上的 32 位版本和 64 位版本放入回收站?仅仅因为它可以完成,并不意味着它是一个好主意。对不起,我不听你的推理。 (6认同)
  • @StephenJennings:但这需要您手动做出决定。它现在的工作方式是该过程是自动的,因为当应用程序调用“SHGetSpecialFolderPath”来确定安装位置时,Windows 知道要提供哪个文件夹。 (4认同)
  • @Synetech:是的,你确实给出了一个很好的例子来说明如何做到这一点。另一个很好的例子是它**是**现在实际完成的方式。简单地将文件写入 %PROGRAMFILES% 并确定它最终会出现在正确的文件夹中是一回事。自己检查哪个文件夹是*正确的* 一个是另一个。如果您实际上没有看到前一种方法的好处,那么我将无法说服您。问题是为什么有 2 个文件夹。在这方面,我认为我的回答是完全合理的。 (4认同)
  • 但这就是最初的原因吗?我不能将应用程序安装到“C:\Program Files\App32”和“C:\Program Files\App64”吗? (3认同)
  • @OliverSalzburg,不完全是。问题是为什么两个文件夹是*必需的*,而不是为什么有*。事实上,他甚至加粗了:**为什么这甚至是必要的?**你没有解释为什么它是**必要的**,我给出的例子(甚至你自己的讽刺例子)只是表明它没有* *必须**按原样完成。 (3认同)
  • **呸!编辑失败...** `@Oliver-Salzburg – 仅供参考 - RE:_“如果我尝试在同一条线路上同时使用交流和直流电会发生什么?”_` 您知道传统的模拟电话系统 (POTS) ) 这样做吗?它们使用 ~45-52VDC 线电压 {T(+grd) & R(-48VDC)} 进行正常操作;然而,要使电话振铃,大约 90-110VAC(标称 20Hz,但有所不同)的信号叠加在空闲线路上已经存在的直流电压上。 (2认同)

Syn*_*ech 14

特尔;博士:

总而言之,不,没有必要;他们可以使用单个文件夹,不,Windows 不会以不同的方式呈现在从一个位置或另一个位置运行的程序。


好吧,似乎每个人都对此发表了自己的看法,所以我将投入 2 美分。其他人已经猜测了为什么Microsoft 选择为 32 位和 64 位版本的程序创建单独的顶级文件夹的原因,所以我将离开那部分(最好的原因是 David 的解释,它是作为一个方便程序员)。当然,即便如此,它也没有完全解决直接的问题,为什么这甚至是必要的?,答案大概是:它不是

相反,我将解决问题的主体

Windows 是否以某种方式以不同的方式呈现出“Program Files (x86)”不足的程序?

不是真的,但程序的位置影响行为,但不会像您想象的那样。

当你运行一个程序时,Windows 会设置一个运行它的环境(我的意思是在内存、寻址等方面,而不仅仅是环境变量)。此环境取决于可执行文件的内容(32 位和 64 位程序内部不同)。当您在 64 位系统上运行 32 位程序时,它会在模拟 32 位环境的 32 位子系统中运行。它被称为WoW64(WoW64 代表Windows 64 位上的 Windows)并且类似于使用NTVDM在 XP 中运行 16 位应用程序的方式。

当您使用或不使用管理员权限运行程序时,它会影响它的运行方式,但位置不应影响它(尽管有一些位置依赖的示例,例如某些驱动程序)。

(我使用的是另一台计算机,所以我不能依靠我的浏览器历史记录来回溯我的步骤,但是前几天在回答这个 SU 问题时,我结束了这个 SO 问题,这导致我使用Google PROCESSOR_ARCHITEW6432这导致了这个 SO 问题这篇 Microsoft 博客文章。)

在此过程中的某个地方,我阅读了 StackOverflow 的一篇文章,内容是关于环境变量如何%processor_architecutre% 根据您运行命令提示符的位置给出不同的结果(我将尝试找到确切的引用)。

答案原来是由于运行的是 32 位还是 64 位版本的命令提示符(即 fromSystem32\SysWoW64\)。换句话说,虽然位置似乎会影响程序的行为,但这只是因为程序的版本不同,而不是因为 Windows 以特殊方式对待文件夹。

这是有道理的,因为可执行文件的内容决定了它是 32 位还是 64 位,因此您可以将同一程序(例如,foobar32.exefoobar64.exe)的 32 位和 64 位副本放在同一文件夹中,并且当您执行它们,它们将被正确加载(64 位版本将在本机运行,32 位版本将在 WoW64 仿真层中运行)。

FreePascal 允许您安装 DOS 和 Windows 版本,它们位于同一个文件夹中:%programfiles%\FreePascal. 它通过将可执行文件(.exe.sys.dll.ovr等)保存在单独的文件夹中并共享资源文件(如图片、源文件等)来管理不同的体系结构。)没有技术原因不能为 32 和程序的 64 位版本。就像大卫说的那样,如果将它们分开对程序员来说会更容易(即,使用变量使其看起来只有一组文件等)


Can*_*uke 11

另一个原因是大多数程序过去使用环境变量(例如 %PROGRAMFILES%)来指向其程序的安装位置。对于 64 位程序,它会转到正常位置。对于 32 位程序,它会将其重定向到新Program Files (x86)文件夹。

虽然,至少对于 Visual Studio 中的新 .Net 内容,他们现在拥有 App.Local 变量,从而消除了对这一点的全部需求。

  • 那不解释了。谁在使用环境变量,为什么它会关心程序是 32 位还是 64 位? (4认同)
  • @Synetech - 程序的作者使用环境变量。至于它会关心的原因是因为对 dll 的引用。您不能在 64 位进程中加载​​ 32 位 dll,反之亦然。 (4认同)

avi*_*irk 9

对于从 32 位到 64 位的这种过渡,Microsoft 的解决方案是添加对大多数 32 位应用程序的旧支持。换句话说,大多数 32 位应用程序将在 64 位操作环境中运行。请记住,在 64 位体系结构上运行的其他操作系统根本无法加载或运行 32 位应用程序。

为帮助简化转换,Microsoft 已指定所有 32 位应用程序默认应加载到 Program Files (x86) 文件夹中,而不是与常规 Program Files 文件夹中的真正 64 位应用程序混合。

来源

“如果我以某种方式避免重定向机制并强制将所有内容安装到真正的 C:\Program Files\ 中,会出现什么问题?”

没有。这两个程序目录仅用于组织,或用于将具有 32 位和 64 位两个版本的程序分开,如 Internet Explorer。但是您可以在“Program Files”中安装 32 位程序,在“Program Files x86”中安装 64 位程序,并且不会发生任何事情,程序将运行相同。

维基说:

某些应用程序安装程序拒绝安装路径位置中的空格。对于 32 位系统,Program Files 文件夹的简称为Progra~1。对于 64 位系统,64 位 Program Files 文件夹的简称为 Progra~1(与 32 位系统相同);而 32 位 Program Files (x86) 文件夹的简称现在是Progra~2


Blu*_*eft 6

原因是为了让开发人员更容易将程序升级到 64 位。在32位模式下编译时,他们不必编写任何自定义代码来检查一个目录中的程序,而在64位模式下编译时则在另一个目录中检查程序;他们只是检查C:\Program Files,当在 32 位模式下运行时,这会自动被C:\Program Files (x86)64 位 Windows更改为。同样,注册表项在 32 位和 64 位程序之间是隔离的。

这可以防止在不知情的情况下将编译模式更改为 64 位而没有考虑太多的开发人员发生冲突,并且可以防止希望用户能够同时安装 32 位和 64 位版本的开发人员的大量工作。软件同时。


但是为什么任何程序都希望允许同时安装两个版本呢?一个示例:Photoshop 和 IE 具有本机 .dll 的扩展名。您不能在同一进程中混合 32 位和 64 位代码,因此 32 位版本的插件不能与 64 位版本一起使用,反之亦然。因此,Photoshop/IE必须允许安装这两个版本,否则可能会破坏其庞大的现有插件基础。

  • +1 至少您解决了为什么普通用户会同时拥有这两个版本的基本问题。 (2认同)

Dio*_*ogo 5

在“Program Files(x86)”上运行的程序使用WOW64子系统(Windows 64 位上的 Windows 32 位是一组旨在在 x64 架构系统上运行 x32 应用程序的驱动程序和 API):

WoW64 子系统包含一个轻量级兼容层,在所有 64 位版本的 Windows 上都具有类似的接口。它旨在创建一个 32 位环境,提供在 64 位系统上运行未经修改的 32 位 Windows 应用程序所需的接口。从技术上讲,WoW64 是使用三个动态链接库 (DLL) 实现的:

  • Wow64.dll,Windows NT 内核的核心接口,在 32 位和 64 位调用之间进行转换,包括指针和调用堆栈操作
  • Wow64win.dll,为 32 位应用程序提供适当的入口点
  • Wow64cpu.dll,负责将处理器从 32 位模式切换到 64 位模式

64 位系统需要“模拟” 32 位应用程序,这就是 Windows 需要“隔离”两个 Program Files 文件夹的原因。

  • 但是为什么要放在不同的文件夹中呢?Windows 已经完全有能力通过查看 PE 标头来确定可执行文件的体系结构。为什么在加载可执行文件的时候加载不了合适的环境呢? (7认同)

Roc*_*ket 5

有趣的是,这里和整个互联网上的答案差别很大。为这个重要问题找到准确的答案一直是一个挑战。互联网上似乎有相当多的虚假信息,导致混乱。

我进行了大量的研究,并得出了以下结论,我认为这是准确的:

  • 应用程序的存储位置没有区别。在运行时,Windows 将确定应用程序是 32 位还是 64 位并自动使用适当的 DLL 和注册表部分。

这会自动发生,并且与应用程序的存储位置无关。拥有单独的 32 位和 64 位文件夹没有速度、可靠性或其他功能优势。

默认分成两个文件夹(“Program Files”和“Program Files (x86)”)的唯一原因是,如果您有同一个程序的两个版本(32 位和 64 位版本),它提供了一个保持重叠文件分开的简单方法。即使在这种情况下,只要所有文件名都是唯一的,它们实际上可以存在于同一文件夹中而不会产生任何后果。

上述结论有一个警告,那就是编码不佳的应用程序之一。如果应用程序有任何硬编码的路径,它将只使用该路径。通常,路径不应该硬编码到应用程序中,但有时程序员会犯这个错误。在这种情况下,程序将使用硬编码路径;安装应用程序的目录不会影响它实际查找文件的位置。