【问题标题】:Why does boost::filesystem is_directory return different results when run as a Windows Service?为什么 boost::filesystem is_directory 在作为 Windows 服务运行时返回不同的结果?
【发布时间】:2011-10-11 19:27:21
【问题描述】:

我有一些代码可以遍历目录中的文件并对非目录文件执行有用的操作,如下所示:

namespace bfs = boost::filesystem;
for (bfs::directory_iterator iterDir(m_inPath); 
     bContinue && iterDir!=bfs::directory_iterator(); iterDir++)
{
    std::string filename = iterDir->path().filename().string();
    boost::to_lower(filename);

    if (!bfs::is_directory(*iterDir) && Condition2(filename)) {
        std::ifstream ifFile(iterDir->path().string().c_str());
        DoUsefulThings(iterDir());
    }
}

这在我的单元测试中运行良好,但是当我将完整程序作为服务运行时,我的测试目录(似乎错误地)通过了 !bfs::is_directory 检查和 DoUsefulThingsifstream.good() 检查失败,并出现错误号为 13。

我尝试将!bfs::is_directory 更改为bfs::is_regular_file(认为可能是系统条件导致它成为其他问题),但我得到了相同的结果。 is_regular_file 条件在我的单元测试中的目录上失败,但在作为服务运行时通过。

我还在 if 语句周围添加了一个 try/catch,以查看它是否引发异常并验证它不是(可能无论如何都可以使用,但对此没有帮助)。

我认为问题可能与服务的权限级别有关,因此我将服务的属性更改为使用与登录该系统相同的帐户登录。结果相同。我也尝试过一些 PerformanceMonitor 以尝试在那里找到一些线索,但我还没有从中收集到太多信息。

有人能说明为什么会发生这种情况吗? Errno=13 == “权限被拒绝”,对吧?在调用 is_directory 之前我需要执行额外的检查吗?

我使用的是 Windows XP、Visual Studio 2008/C++、Boost 库版本 1.44 和文件系统版本 3。

ETA:我添加了以下内容以手动测试目录(斜线标记的方向没有影响),并且 is_regular_file 的行为符合预期:

std::string strDir = "D:/Dir1/Dir2/Dir3/Dir4/Dir5\\Dir6";
if (bfs::is_regular_file(strDir))
    LOG("It's a regular file"); //This does not get executed
else
    LOG("Not a regular file");  //This does

我有打印出 *iterDir 和 iterDir->path() 的日志语句,它们都与我手动输入的相匹配。这是否排除了权限问题?将继续测试,因为这个结果对我来说还没有意义。

【问题讨论】:

  • 权限...我猜该目录不可访问/不可遍历
  • 那么实际的目录路径是什么?它可能是服务无法访问的 UNC 路径,或者它可能是映射到驱动器的远程共享,而映射对服务不可见。该路径会提示您为什么服务看不到它。
  • 您也可以尝试在用户凭据下运行服务,而不是默认的LocalService
  • @sehe:我尝试手动设置目录的权限以允许“所有人”完全访问。我还尝试在同一位置添加另一个目录(认为另一个目录可能以某种方式被破坏)。两者仍然通过 if(bfs::is_regular_file)。
  • @Roman R. 路径可能确实是一个线索。它的格式为“D:/Dir1/Dir2/Dir3/Dir4/Dir5/Dir6\Dir7”。我会调查一下,看看斜线是否引起了问题。我确实尝试在用于登录系统的相同凭据下运行该服务,但这似乎没有任何区别。

标签: windows boost windows-services boost-filesystem


【解决方案1】:

@Ennael:

不要忘记,您需要对尝试访问的文件夹的所有父文件夹/设备节点具有遍历权限。我认为 Roman 的建议将首先消除疑虑(这当然是非常不合理的:Errno=13 == "permission denied")。

你可以从那里开始使用类似的工具

  • cacls.exe

做命令行 ACL 列表/编辑

  • AccessEnum v1.32 检测文件系统树中权限的任何更改(有一个漂亮的选项,仅在权限变得更受限制或更宽松时发出警告)

【讨论】:

  • 我授予“所有人”对该目录及其所有父目录(包括驱动器本身)的完全访问权限。我也在我的登录名下运行该服务(而不是 LocalService)。 AccessEnum 和 cacls 确认目录的权限,并且 AccessEnum 在重新运行服务后仍然给我相同的结果。我会更多地阅读/思考这些工具。谢谢。
【解决方案2】:

呸。这是我的“Condition2”中的一个错误。感谢您的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-28
    • 2012-07-28
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多