【问题标题】:Verify whether 'C:\Program Files\' is writable验证“C:\Program Files\”是否可写
【发布时间】:2013-12-14 16:35:14
【问题描述】:

我有一种情况,用户可以配置某些文件的目标位置(正在下载和安装以与应用程序一起使用)。有两个配置的位置,一个系统位置和一个用户位置。该应用程序是一个(基于 Lua 的)命令行工具。

在安装之前,我通过写入一个临时文件并再次删除它来检查可写位置。如果失败,我会以提升的权限重新启动相同的命令,允许管理员安装,但不允许普通用户安装。

问题:系统位置默认位于C:\Program Files\ 内,受保护(不是问题)并重定向(这是问题)到C:\Users\<name>\AppData\VirtualStore\Program Files\... 目录。 由于这种重定向测试成功,正在安装的东西没有提升特权。因此最终出现在VirtualStore,而不是收到用户没有所需权限的错误。

问题:那么如何在不调用到 VirtualStore 的重定向的情况下测试实际的 C:\Program Files\ 是否可写?

【问题讨论】:

  • Wow64DisableWow64FsRedirection.
  • @Sneftel 那是为了 64/32 位兼容性。不适用于与我的问题相关的 UAC。然后还有;我只能访问命令行命令或 Lua 脚本。不适用于任何 Windows API 函数。
  • 不会检查您的管理员权限是否足够?
  • @npocmaka 不,因为位置是可配置的,所以如果它位于不需要管理员权限的位置,它应该可以正常工作,而无需不必要地请求管理员权限。
  • 我不知道细节,但 UAC 虚拟存储重定向只发生在某些可执行文件中,因此您可以通过在清单中放置适当的标志来使您的程序免受它的影响。跨度>

标签: windows batch-file command-line lua command-prompt


【解决方案1】:

我尝试了一些技巧来查看哪些命令被重定向,哪些没有。 最初,我尝试使用 os copy 命令将临时文件复制到同一位置的第二个临时文件,但在这种情况下,既要读取源又要写入重定向的目标。

这个 Lua 代码给出了最终的结论;

function is_writable(file)
   assert(file)
   file = dir.normalize(file)
   local result
   local tmpname = 'tmptestwritable.deleteme'
   if fs.is_dir(file) then
      local file2 = dir.path(file, tmpname)
      local fh = io.open(file2, 'wb')
      result = fh ~= nil
      if fh then fh:close() end
      if result then
         -- the above test might give a false positive when writing to
         -- c:\program files\ because of VirtualStore redirection on Vista and up
         -- So get a directory listing and check whether it's really there
         local pipe = io.popen("dir "..fs.Q(file))
         local dir_list = pipe:read("*a")
         pipe:close()
         result = (nil ~= string.find(dir_list, tmpname, 1, true))
      end
      os.remove(file2)
   else
      local fh = io.open(file, 'r+b')
      result = fh ~= nil
      if fh then fh:close() end
   end
   return result
end

在常规“编写测试文件”之后,它在目标文件夹上执行dir 命令,该命令仅返回内容而不进行重定向,然后在此内容中搜索使用的临时名称。

感谢您的努力!

【讨论】:

  • +1。作为一种优化,由于cmd.exe 没有重定向,所以应该可以使用io.popen("if exist ... 之类的东西而不是搜索输出,甚至可以使用io.popen 来尝试首先写入文件。
  • @Harry 刚刚测试了它,你是对的。 “IF EXIST”被广泛使用,但只是没有在应用程序的这一部分中使用,因此我得出结论认为它不起作用。我的错,这确实是一种简化。
【解决方案2】:

这行得通吗?

@echo off
2>nul (
(call ) >>"C:\Program Files\file"
) && (
   rem we have access
   rem do stuff
   exit /b
)
rem we dont have access
rem do stuff

如果不是,恐怕我不明白你的问题,所以请解释一下它没有解决什么问题。

【讨论】:

  • 但是问题不就是会把数据重定向到virtualstore而且这个操作永远不会失败吗?
  • 我不知道,当我测试它的时候它工作了,但也许那是因为我使用了一个管理员帐户
【解决方案3】:
del /q /f "C:\Users\%username%\AppData\Local\VirtualStore\Program Files\redirectionTest" >nul 2>&1
echo test>"%ProgramFiles%\redirectionTest"
if exist "C:\Users\%username%\AppData\Local\VirtualStore\Program Files\redirectionTest" (
  echo redirected
) else (
  echo not redirected
)

??

或者可能只是:

echo test>"%ProgramFiles%\redirectionTest"
if exist "%ProgramFiles%\redirectionTest" echo not redirected

IF EXIST 是否也被重定向了?

【讨论】:

  • 是的,If EXIST 也被重定向,我们广泛使用它。甚至 GNU ls.exe 命令(与我们的应用程序捆绑在一起)也将目录的内容列为真实和虚拟位置的组合内容。所以即使现在是个问题,我认为微软在实现它方面做得很好,非常透明。
  • 至少删除VirtualStore 中的临时文件并在ProgramFiles 中创建它,然后再次检查VirtualStore 应该可以工作..
  • 我没有测试它,因为我当前的解决方案有效。我对直接访问 VirtualStore 犹豫不决的原因是我不确定 Program Files 是否是唯一的重定向位置,或者是否还有更多。我当前的解决方案,捕获dir 命令输出并验证,将适用于每个位置。
  • @Tieske: AFAIK,没有原生 cmd.exe 函数被重定向,这应该包括 if exist;也许您在谈论 Lua 的等效功能?
  • 我上面关于IF EXIST 也被重定向的评论是错误的。它不是。感谢@Harry 指出这一点。
猜你喜欢
  • 2014-01-29
  • 1970-01-01
  • 2010-11-05
  • 1970-01-01
  • 2017-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多