【问题标题】:Ruby Dir.foreach in System32 misses files / File.exists? returns false for existing filesSystem32 中的 Ruby Dir.foreach 缺少文件/File.exists?对现有文件返回 false
【发布时间】:2012-08-25 13:11:38
【问题描述】:

当我使用 ruby​​ 打印出 windows 7 system32 目录中的所有文件时,一些文件丢失了。我使用这个简单的目录迭代:

Dir.foreach("C:\\Windows\\System32") do |fname|
  puts fname
end

我专门寻找python27.dll,虽然它存在,但它没有打印出来。文件已存在?似乎与 dir 迭代有相同的问题。它为现有文件返回 false:

File.exists? "C:\\Windows\\System32\\python27.dll" #returns false

检查文件夹的另一个现有文件是否有效:

File.exists? "C:\\Windows\\System32\\quartz.dll" #returns true

但如果我复制现有文件或在 system32 中创建一个新文件,它不起作用

File.exists? "C:\\Windows\\System32\\quartz2.dll" #returns false

另外,将 python27.dll 复制到另一个目录并检查是否存在:

File.exists? "C:\\Otherfolder\\python27.dll" #returns true

问题与字母大小写或路径分隔符无关。我检查了那个。另外,我看不到有效文件和无效文件的用户权限存在差异......

我真的不知道,为什么会这样……谁能重现这个???

谢谢

[编辑]

花了一段时间,但我找到了答案。

这是一个 32/64 位问题。对于 ruby​​ 作为 32 位应用程序,“C:\Windows\System32”实际上是“C:\Windows\SysWOW64”。正如 64 位 WinExplorer 显示的那样,python27.dll 在 System32 中(只有 64 位进程可以看到 - 好吧,令人困惑),而它应该在 SysWOW64 中才能看到。安装 32 位版本的 Python 为我解决了这个问题(因为我无法更改 ruby​​ 脚本,因为它是 ruby​​python 的一部分)。

【问题讨论】:

  • 我不认为这是问题所在,但我更喜欢使用 / 而不是 \ 或蒙面的 \\,即使在我使用 Windows 时也是如此。 / 工作正常,使用 \ 我遇到了问题。还有File::SEPARATOR,你可以用File.join构建路径。

标签: ruby windows system32 rubypython


【解决方案1】:

在 Windows 7(实际上是 Vista)中,许多在早期版本的 Windows 中仅存在于纸面上的安全策略现在实际上由操作系统强制执行。例如,根据微软的文档,几十年来写信给C:\Windows\System32 几乎是违法的,但如果你真的尝试过,它仍然有效。不再。在 Vista 中,C:\Windows\System32 是禁止使用的。

但是,为了不破坏现有(损坏的)应用程序,Microsoft 引入了文件系统虚拟化。如果应用程序尝试写入C:\Windows\System32,它会被静默重定向到C:\Users\%Username%\AppData\Local\VirtualStore\Windows\System32。因此,这个特定的应用程序可以看到它在C:\Windows\System32 中创建或更改的所有文件,但其他 应用程序只能看到未更改的/空目录。

这不仅适用于C:\Windows\System32,也适用于其他系统目录。此外,它适用于注册表的系统部分,例如 HKEY_LOCAL_MACHINE

这种虚拟化是针对每个应用程序的。 IE。如果应用程序 A 试图在受保护的目录中创建或修改文件,Windows 将拦截该调用并将其重定向到 VirtualStore。它还会在某处记录此重定向。现在,当同一个应用程序 A 再次尝试查看那里时,Windows 将使用记录的重定向,以便应用程序认为文件在它放置的位置,而事实上,它完全在其他地方。

但是,如果不同应用程序 B 查看该目录,则不会触发重定向,B 只会看到一个原始系统目录。这就是重点:在过去,不同的应用程序会通过覆盖彼此在系统目录中的文件来创建各种奇怪的错误。 IE。一个应用程序会将其python27.dll 转储到C:\Windows\System32,而另一个应用程序将转储自己的python27.dll 的不兼容版本,覆盖第一个。

所以,您使用 一个 应用程序将 DLL 复制到那里(可能是 explorer.exe),然后使用 不同 应用程序,即 ruby.exe 来查看它。但是explorer.exe 并没有实际上将它复制到system32,它被重定向到了 VirtualStore。当您使用explorer.exe 时,重定向会被触发,并且您会在认为 放置它的位置看到该文件,但是当您使用ruby.exe 时,重定向会被触发,它会看到实际的目录。

打赌

File.exists? "C:/Users/#{ENV['Username']}/AppData/Local/VirtualStore/Windows/System32/python27.dll"

返回true

【讨论】:

  • 感谢您的回答。有价值的信息和一个很好的猜测。实际问题是 32/64 位问题。
  • @CodeSalad:是的,这基本上是同一件事,但目的不同。
【解决方案2】:

您确定这些文件在C:\\Windows\\System32\\ 中可用吗?

我从System32-文件夹中不知道这个问题,但我在Program Files-文件夹中遇到了一些像你这样的问题。

如果您尝试将数据保存在某些系统文件夹中并且您不是管理员,Win7 不会将其存储在该位置,而是在用户特定的虚拟存储中。当您查看系统文件夹时,虚拟存储中的文件也会显示在那里。但路径是另一条路。

您可以在c:\users\<username>\Appdata\local\Virtual Store\ 的任何地方查看您的虚拟商店(至少程序文件夹在那里)。

【讨论】:

  • 感谢您的回答。有价值的信息和一个很好的猜测。实际问题是 32/64 位问题。
【解决方案3】:

我也遇到了同样的问题,结果证明当使用超过 260 个符号的路径时,ruby 会出现这种情况:

  Administrator@WIN-NUMKGBH6IIM ~
  $ mkdir -p /cygdrive/c/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/

  Administrator@WIN-NUMKGBH6IIM ~
  $ /cygdrive/c/opscode/chef/embedded/bin/ruby <<'EOF'
  puts File.exists?("C:/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/")
  EOF

  true

  Administrator@WIN-NUMKGBH6IIM ~
  $ /cygdrive/c/opscode/chef/embedded/bin/ruby <<'EOF'
  puts File.exists?("C:/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/")
  EOF

  false

【讨论】:

    猜你喜欢
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 2017-08-16
    • 2012-10-22
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    相关资源
    最近更新 更多