System32中的Ruby Dir.foreach错过了files / File.exists?对现有文件返回false

时间:2012-08-25 13:11:39

标签: ruby windows system32 rubypython

当我使用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

问题与letter-case或路径分隔符无关。我查了一下。此外,我没有看到有效的文件的用户权限的差异......

我真的不知道,为什么会发生这种情况......任何人都可以重现这个???

感谢

[编辑]

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

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

3 个答案:

答案 0 :(得分:3)

在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

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

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

因此,您使用一个应用程序在那里复制DLL(可能是explorer.exe)并使用不同的应用程序,即ruby.exe来看它。但是explorer.exe没有实际将其复制到system32,它被重定向到VirtualStore。当您使用explorer.exe时,重定向会被触发,您会看到文件正确的位置 think ,但是当您使用ruby.exe时,重定向 not 被触发,它会看到实际的目录。

下注

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

返回true

答案 1 :(得分:2)

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

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

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

您可以在c:\users\<username>\Appdata\local\Virtual Store\的任何位置检查您的虚拟商店(至少有Program-folder存在)。

答案 2 :(得分:0)

我遇到了同样的问题,事实证明,当处理超过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