{"id":9913,"date":"2011-08-12T07:00:00","date_gmt":"2011-08-12T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/08\/12\/readdirectorychangesw-reads-directory-changes-but-what-if-the-directory-doesnt-change\/"},"modified":"2024-06-10T15:09:50","modified_gmt":"2024-06-10T22:09:50","slug":"20110812-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20110812-00\/?p=9913","title":{"rendered":"ReadDirectoryChangesW reads directory changes, but what if the directory doesn&#8217;t change?"},"content":{"rendered":"<p>The <code>Read\u00adDirectory\u00adChangesW<\/code> function reads changes to a directory. But not all changes that happen to files in a directory result in changes to the directory.<\/p>\n<p>Now, it so happens that nearly all changes to a file in a directory really do result in something happening to the file&#8217;s directory entry. If you write to a file, the last-write time in the directory entry changes. If you rename a file, the name in the directory entry changes. If you create a file, a new directory entry is created.<\/p>\n<p>But there are some changes that do not affect the directory entry. I&#8217;ve heard rumors that if you write to a file via a memory-mapped view, that will not update the last-write time in the directory entry. (I don&#8217;t know if it&#8217;s true, but if it&#8217;s not, then just pick some other file-modifying operation that doesn&#8217;t affect the directory entry, like modifying the contents of a file through a hard link in another directory, or explicitly suppressing file timestamp changes by calling <code>Set\u00adFile\u00adTime<\/code> with a timestamp of <code>0xFFFFFFFF`<wbr \/>FFFFFFFF<\/code>.) The point is that since these changes have no effect on the directory, they are not recognized by <code>Read\u00adDirectory\u00adChangesW<\/code>. The <code>Read\u00adDirectory\u00adChangesW<\/code> function tells you about changes to the directory; if something happens that doesn&#8217;t change the directory, then <code>Read\u00adDirectory\u00adChangesW<\/code> will just shrug its shoulders and say, &#8220;Hey, not my job.&#8221;<\/p>\n<p>If you need to track all changes, even those which do not result in changes to the directory, you need to look at other techniques like the <a href=\"http:\/\/msdn.microsoft.com\/aa363798.aspx\"> change journal<\/a> (a.k.a. USN journal).<\/p>\n<p>The intended purpose of the <code>Read\u00adDirectory\u00adChangesW<\/code> function is to assist programs like Windows Explorer which display the contents of a directory. If something happens that results in a change to the directory listing, then it is reported by <code>Read\u00adDirectory\u00adChangesW<\/code>. In other words, <code>Read\u00adDirectory\u00adChangesW<\/code> tells you when the result of a <code>Find\u00adFirst\u00adFile<\/code>\/<wbr \/><code>Find\u00adNext\u00adFile<\/code> loop changes. The intended usage pattern is doing a <code>Find\u00adFirst\u00adFile<\/code>\/<wbr \/><code>Find\u00adNext\u00adFile<\/code> to collect all the directory entries, and then using the results from <code>Read\u00adDirectory\u00adChangesW<\/code> to update that collection incrementally.<\/p>\n<p>In other words, <code>Read\u00adDirectory\u00adChangesW<\/code> allows you to optimize a directory-viewing tool so it doesn&#8217;t have to do full enumerations all the time.<\/p>\n<p>This design philosophy also explains why, if too many changes have taken place in the directory between calls to <code>Read\u00adDirectory\u00adChangesW<\/code>, the function will fail with an error called <code>ERROR_<wbr \/>NOTIFY_<wbr \/>ENUM_<wbr \/>DIR<\/code>. It&#8217;s telling you, &#8220;Whoa, like so much happened that I couldn&#8217;t keep track of it all, so you&#8217;ll just have to go back and do another <code>Find\u00adFirst\u00adFile<\/code>\/<wbr \/><code>Find\u00adNext\u00adFile<\/code> loop.&#8221;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Not all changes within a directory result in the directory changing.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-9913","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Not all changes within a directory result in the directory changing.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/9913","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=9913"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/9913\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=9913"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=9913"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=9913"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}