设置为 ReadDirectoryChangesW 打开的目录的上次修改时间

发布于 2024-07-26 20:31:53 字数 1412 浏览 8 评论 0原文

我有一个 Java 程序,需要监视目录树的更改。 我有使用 ReadDirectoryChangesW() 的 JNI 代码。 该目录的打开方式如下:

HANDLE dirHandle = CreateFile(
    path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL
);

然后我将 dirHandle 传递给 ReadDirectoryChangesW()。 所有这些都运行得很好。

问题在于代码的其他部分(在 Java 端)使用 File.setLastModified() 来“触摸”文件或目录(将其时间戳更新为“现在”)。 这通常是有效的; 但是,当它尝试“触摸”使用 CreateFile() 打开的目录时,它会失败。

为了了解实际发生的 Windows 错误,我查看了 File.setLastModified() 的 JDK 源代码,并在我自己的代码中重新实现了它,并从 GetLastError()< 打印了错误/代码>; 错误是:

ERROR_SHARING_VIOLATION (error 32)
"The process cannot access the file because it is being used by another process."

WTF? 这是相同的过程。 我什至将 FILE_SHARE_READFILE_SHARE_WRITE 传递给 CreateFile()

有办法让这项工作发挥作用吗?

更多信息

JDK 中 File.setLastModified() 的本机代码实现执行以下操作:

h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);

如果我将第一个 0 更改为 FILE_SHARE_READ | FILE_SHARE_WRITE,一切正常。 所以看来JDK的实现有点破损。 :(

所以我现在的问题变成了:有没有一种方法可以使这项工作无需使用我自己的(重新)实现 File.setLastModified()

I hava a Java program that needs to monitor a directory tree for changes. I have JNI code that uses ReadDirectoryChangesW(). The directory is opened like:

HANDLE dirHandle = CreateFile(
    path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL
);

and then I pass dirHandle to ReadDirectoryChangesW(). All of that works just fine.

The problem is that other parts of the code (on the Java side) use File.setLastModified() to "touch" files or directories (update their timestamps to be "now"). This generally works; however, it fails when it tried to "touch" the directory that was opened using CreateFile().

To see what Windows error is actually occurring, I looked at the JDK source for File.setLastModified() and reimplemented it in my own code with the addition of printing the error from GetLastError(); the error is:

ERROR_SHARING_VIOLATION (error 32)
"The process cannot access the file because it is being used by another process."

WTF? It's the same process. I even passed FILE_SHARE_READ and FILE_SHARE_WRITE to CreateFile().

Is there a way to make this work?

More Info

The native code implementation of File.setLastModified() in the JDK does a:

h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);

If I change the first 0 to FILE_SHARE_READ | FILE_SHARE_WRITE, it all works. So it seems that the JDK implementation is a little broken. :(

So my question now becomes: Is there a way to make this work without having to use my own (re)implementation of File.setLastModified()?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

徒留西风 2024-08-02 20:31:53

尽管在这种情况下错误消息有点误导,但您看到的是正常行为。

通过将 dwShareMode 设置为零打开目录,JDK 实际上会请求独占访问,这将导致任何其他访问尝试失败并出现共享冲突错误。 这同样适用于访问
来自其他流程和您自己的流程。

CreateFile 文档介绍了 dwShareMode 参数:

如果此参数为零且 CreateFile 成功,则文件或设备无法共享且无法再次打开,直到文件或设备的句柄关闭。

您请求的共享模式不能与具有打开句柄的现有请求中指定的访问模式冲突。 CreateFile 将失败,GetLastError 函数将返回 ERROR_SHARING_VIOLATION

所以,看来您已经回答了自己的问题:您需要一个自定义 setLastModified 函数来指定 FILE_SHARE_READ | 访问目录时FILE_SHARE_WRITE

Although the error message is a bit misleading in this case, what you're seeing is normal behaviour.

By opening the directory with dwShareMode set to zero, the JDK is, in effect, asking for exclusive access, which will cause any other access attempt to fail with a sharing violation error. This applies equally to accesses
from other processes and from within your own process.

The CreateFile documentation describes the dwShareMode parameter:

If this parameter is zero and CreateFile succeeds, the file or device cannot be shared and cannot be opened again until the handle to the file or device is closed.

You cannot request a sharing mode that conflicts with the access mode that is specified in an existing request that has an open handle. CreateFile would fail and the GetLastError function would return ERROR_SHARING_VIOLATION.

So, it seems you've answered your own question: you need a custom setLastModified function that specifies FILE_SHARE_READ | FILE_SHARE_WRITE when accessing the directory.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文