• .NET : 使用ReadDirectoryChangesW监控文件夹的变化


    近日在讨论到之前我发布的“文件同步工具”时,有朋友建议用ReadDirectoryChangesW方法去做监控。我个人觉得,如果在C#中做监控的话,首选还是.NET Framework封装好的FileSystemWatcher去做。但我以为,监控也有监控的烦恼,就是说要一直监控。而一旦中途停止监控,又自然会涉及到一个状态保存的问题。

    我刚才将该函数看了一下,做了一个范例,如下。如果有兴趣的朋友,可以参考一下

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode,
      IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes,
      IntPtr hTemplateFile);

    [DllImport("kernel32.dll")]
    static extern bool CloseHandle(IntPtr hObject);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
    static extern bool ReadDirectoryChangesW(IntPtr hDirectory, IntPtr lpBuffer, uint nBufferLength,
      bool bWatchSubtree, uint dwNotifyFilter, out uint lpBytesReturned, IntPtr lpOverlapped,
      IntPtr lpCompletionRoutine);

    static void Main(string[] args)
    {

        const uint FILE_LIST_DIRECTORY = 0x1;
        const uint FILE_SHARE_READ = 0x1;
        const uint FILE_SHARE_WRITE = 0x2;
        const uint FILE_SHARE_DELETE = 0x4;
        const uint OPEN_EXISTING = 3;
        const uint FILE_FLAG_BACKUP_SEMANTICS = 0x2000000;
        const uint FILE_NOTIFY_CHANGE_FILE_NAME = 0x1;
        const uint FILE_NOTIFY_CHANGE_DIR_NAME = 0x2;
        const uint FILE_NOTIFY_CHANGE_LAST_WRITE = 0x10;

        const uint BUFSIZE = 2048;
        string myDocs = @"E:\Temp";
        Console.WriteLine("Monitoring name changes in {0} and subdirectories.", myDocs);

        IntPtr hDir = CreateFile(myDocs, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE |
          FILE_SHARE_DELETE, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero);
        if (hDir == IntPtr.Zero)
        {
            Console.WriteLine("CreateFile failed. " + Marshal.GetLastWin32Error());
            return;
        }

        IntPtr pBuf = IntPtr.Zero;
        try
        {
            pBuf = Marshal.AllocHGlobal((int)BUFSIZE);
            uint bytesReturned;
            while (ReadDirectoryChangesW(hDir, pBuf, BUFSIZE, true, FILE_NOTIFY_CHANGE_FILE_NAME |
                   FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE, out bytesReturned,
                   IntPtr.Zero, IntPtr.Zero))
            {
                string[] actions = new string[] { "(unknown action) ", "Added ", "Removed ",
                                  "Modified ", "Old name ", "New name " };
                IntPtr pCurrent = pBuf;
                while (pCurrent != IntPtr.Zero)
                {
                    // Read file length (in bytes) at offset 8
                    int fileLen = Marshal.ReadInt32(pCurrent, 8);
                    // Read file name (fileLen/2 characters) from offset 12
                    string file = Marshal.PtrToStringUni((IntPtr)(12 + (int)pCurrent), fileLen / 2);
                    // Read action at offset 4
                    int action = Marshal.ReadInt32(pCurrent, 4);
                    if (action < 1 || action >= actions.Length) action = 0;
                    Console.WriteLine(actions[action] + file);

                    // Read NextEntryOffset at offset 0 and move pointer to next structure if needed
                    int inc = Marshal.ReadInt32(pCurrent);
                    pCurrent = inc != 0 ? (IntPtr)(inc + (int)pCurrent) : IntPtr.Zero;
                }
            }
            //else
                //Console.WriteLine("ReadDirectoryChangesW failed. " + Marshal.GetLastWin32Error());
        }
        finally
        {
            if (pBuf != IntPtr.Zero) Marshal.FreeHGlobal(pBuf);
            CloseHandle(hDir);
        }

        Console.Read();
    }

    本文由作者:陈希章 于 2009/8/9 8:06:22 发布在:博客园,转载请注明出处
  • 相关阅读:
    Python常用模块学习
    如何在cmd下切换不同版本的Python
    Python3
    Python第二模块(文件和函数)
    Hibernate教程一览
    struts2框架一览
    Java正式day_04——嵌套循环
    AJAX
    JS+JQUERY
    Mybatis注意问题
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/1542115.html
Copyright © 2020-2023  润新知