监视文件夹并查找文件是否在

监视文件夹并查找文件是否在

本文介绍了监视文件夹并查找文件是否在 Windows 应用程序中打开的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很明显,没有简单或方便的方法可以知道文件是否打开/被进程保存.我认为这是 Windows 操作系统本身的一个问题或设计决策,因为即使像 Process Explorer 这样的程序也无法判断我何时在记事本中打开了mytext.txt"文件,除了它的窗口 :) 进一步的研究也显示了获取的唯一方法这些信息可靠地深入研究系统驱动程序.我的问题仍然存在,如果有人可以向我展示此驱动程序解决方案的路径,我也很感激.

So apparently there is no simple or convenient way of knowing if a file is open / being held by a process. I think this is a problem or design decision of Windows OS itself because even programs like Process Explorer can't tell when I have "mytext.txt" file is open in notepad right besides it's window :) further research also showed only way to get this information reliably is to dvelve into system drivers. My question still stands and if anyone can show me a path to this driver solution that is also appreciated.

ps:我真诚地认为应该有一个简单的解决方案来解决这个问题.我的意思是,感觉这是整个操作系统中缺少的一个功能 - 无法判断文件是否打开?真的吗?甚至不是 API 方法?我觉得这不太对.

p.s: I sincerely think there should be a simple solution to this answer. I mean, it feels like it's a feature missing in a whole OS - can't tell if a file is open? Really? Not even an API method? This doesn't feel right to me.

-- 原始问题--

我一直在网上搜索以找到这个问题的答案.显然在 Windows Vista 之后添加了一个名为 Restart Manager 的功能,我们可以调用该 dll 的方法来检查文件是否被锁定.

I've been searching all around the web to find an answer to this. Apparently after Windows Vista there is a feature called Restart Manager was added and we can invoke that dll's methods to check if a file locked or not.

但是,当我在一个简单的控制台应用程序中尝试此操作时(受本文启发:https://blogs.msdn.microsoft.com/oldnewthing/20120217-00/?p=8283 和这个 SO 答案 https://stackoverflow.com/a/20623311/1858013)它可以判断办公室文件(xls、doc 等)是否已锁定/打开,但在我打开 .txt 文件中的记事本,或 .sln 文件,当我在 Visual Studio 中打开一个项目时.

However, when I try this in a simple console app (inspired by this article: https://blogs.msdn.microsoft.com/oldnewthing/20120217-00/?p=8283 and this SO answer https://stackoverflow.com/a/20623311/1858013) it can tell if an office file (xls, doc etc...) is locked / open but not when I open a .txt file in Notepad, or a .sln file when I have a project open in Visual Studio.

我的程序正在监视用户系统中的预设文件夹(例如 Documents 文件夹),我想在该文件夹中打开任何文件时触发一个事件.程序本身不会修改文件或使用该文件,因此锁定或解锁不是问题,我只想在受监控文件夹中的任何程序中打开文件时收到通知.

My program is monitoring a preset folder in user's system (say, Documents folder) and I want to trigger an event when any file is opened in that folder. The program itself won't modify the file or do work with that file so locking or unlocking is not a problem, I simply want to be notified when a file is opened in any program in the monitored folder.

现在,我正在使用此代码来查找哪些进程正在锁定文件,但我觉得有一种比使用 Win32 api 更容易知道文件何时被打开的方法.

Right now, I'm using this code to find which processes are locking a file but I feel there is an easier way to know when a file is opened than using Win32 apis.

static public class FileUtil
{
    [StructLayout(LayoutKind.Sequential)]
    struct RM_UNIQUE_PROCESS
    {
        public int dwProcessId;
        public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
    }

    const int RmRebootReasonNone = 0;
    const int CCH_RM_MAX_APP_NAME = 255;
    const int CCH_RM_MAX_SVC_NAME = 63;

    enum RM_APP_TYPE
    {
        RmUnknownApp = 0,
        RmMainWindow = 1,
        RmOtherWindow = 2,
        RmService = 3,
        RmExplorer = 4,
        RmConsole = 5,
        RmCritical = 1000
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct RM_PROCESS_INFO
    {
        public RM_UNIQUE_PROCESS Process;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)]
        public string strAppName;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)]
        public string strServiceShortName;

        public RM_APP_TYPE ApplicationType;
        public uint AppStatus;
        public uint TSSessionId;
        [MarshalAs(UnmanagedType.Bool)]
        public bool bRestartable;
    }

    [DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
    static extern int RmRegisterResources(uint pSessionHandle,
                                          UInt32 nFiles,
                                          string[] rgsFilenames,
                                          UInt32 nApplications,
                                          [In] RM_UNIQUE_PROCESS[] rgApplications,
                                          UInt32 nServices,
                                          string[] rgsServiceNames);

    [DllImport("rstrtmgr.dll", CharSet = CharSet.Auto)]
    static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey);

    [DllImport("rstrtmgr.dll")]
    static extern int RmEndSession(uint pSessionHandle);

    [DllImport("rstrtmgr.dll")]
    static extern int RmGetList(uint dwSessionHandle,
                                out uint pnProcInfoNeeded,
                                ref uint pnProcInfo,
                                [In, Out] RM_PROCESS_INFO[] rgAffectedApps,
                                ref uint lpdwRebootReasons);

    /// <summary>
    /// Find out what process(es) have a lock on the specified file.
    /// </summary>
    /// <param name="path">Path of the file.</param>
    /// <returns>Processes locking the file</returns>
    /// <remarks>See also:
    /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa373661(v=vs.85).aspx
    /// http://wyupdate.googlecode.com/svn-history/r401/trunk/frmFilesInUse.cs (no copyright in code at time of viewing)
    ///
    /// </remarks>
    static public List<Process> WhoIsLocking(string path)
    {
        uint handle;
        string key = Guid.NewGuid().ToString();
        List<Process> processes = new List<Process>();

        int res = RmStartSession(out handle, 0, key);
        if (res != 0) throw new Exception("Could not begin restart session.  Unable to determine file locker.");

        try
        {
            const int ERROR_MORE_DATA = 234;
            uint pnProcInfoNeeded = 0,
                 pnProcInfo = 0,
                 lpdwRebootReasons = RmRebootReasonNone;

            string[] resources = new string[] { path }; // Just checking on one resource.

            res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null);

            if (res != 0) throw new Exception("Could not register resource.");

            //Note: there's a race condition here -- the first call to RmGetList() returns
            //      the total number of process. However, when we call RmGetList() again to get
            //      the actual processes this number may have increased.
            res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons);

            if (res == ERROR_MORE_DATA)
            {
                // Create an array to store the process results
                RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
                pnProcInfo = pnProcInfoNeeded;

                // Get the list
                res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons);
                if (res == 0)
                {
                    processes = new List<Process>((int)pnProcInfo);

                    // Enumerate all of the results and add them to the
                    // list to be returned
                    for (int i = 0; i < pnProcInfo; i++)
                    {
                        try
                        {
                            processes.Add(Process.GetProcessById(processInfo[i].Process.dwProcessId));
                        }
                        // catch the error -- in case the process is no longer running
                        catch (ArgumentException) { }
                    }
                }
                else throw new Exception("Could not list processes locking resource.");
            }
            else if (res != 0) throw new Exception("Could not list processes locking resource. Failed to get size of result.");
        }
        finally
        {
            RmEndSession(handle);
        }

        return processes;
    }
}

任何帮助将不胜感激.

推荐答案

你需要知道谁打开了一个文件,还是你只需要知道它是否被锁定.

Do you need to know who opened a file or do you just need to know if it is locked.

如果您只需要知道它是否被锁定,您可以使用 FileSystemWatcher.该组件将监控某个文件夹的各种变化.

In case you just need to know if it is locked you can use FileSystemWatcher. This component will monitor a certain folder for various changes.

这篇关于监视文件夹并查找文件是否在 Windows 应用程序中打开的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 19:26