如何检查另一个应用程序是否正在使用某个文件?

时间:2015-06-30 12:05:57

标签: c winapi

我使用以下代码检查另一个应用程序是否正在使用该文件:

HANDLE fh = CreateFile("D:\\1.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (fh == INVALID_HANDLE_VALUE)
{
    MessageBox(NULL, "The file is in use", "Error", 0);
}

如果该文件正被其他应用程序使用,则会显示该消息框。但是,如果文件不存在,也会显示消息框!

那么我应该怎么做才能解决这个问题,我是否还要检查文件是否存在(使用其他功能),还是可以将CreateFile()的参数更改为仅返回INVALID_HANDLE_VALUE文件正在使用并确实存在?

2 个答案:

答案 0 :(得分:4)

如果您想了解哪个进程打开了文件,请使用Restart Manager。该程序包括以下步骤(如Raymond Chen的博客文章How do I find out which process has a file open?中所述):

  1. 创建一个Restart Manager会话(RmStartSession)。
  2. 将文件资源添加到会话(RmRegisterResource)。
  3. 询问受该资源影响的所有进程的列表(RmGetList)。
  4. 关闭会话(RmEndSession)。
  5. <小时/> 示例代码:

    #include <Windows.h>
    #include <RestartManager.h>
    #pragma comment(lib, "Rstrtmgr.lib")
    
    bool IsFileLocked( const wchar_t* PathName ) {
        bool isFileLocked = false;
    
        DWORD dwSession = 0x0;
        wchar_t szSessionKey[CCH_RM_SESSION_KEY + 1] = { 0 };
        if ( RmStartSession( &dwSession, 0x0, szSessionKey ) == ERROR_SUCCESS ) {
            if ( RmRegisterResources( dwSession, 1, &PathName,
                                      0, NULL, 0, NULL ) == ERROR_SUCCESS ) {
                DWORD dwReason = 0x0;
                UINT nProcInfoNeeded = 0;
                UINT nProcInfo = 0;
                if ( RmGetList( dwSession, &nProcInfoNeeded,
                                &nProcInfo, NULL, &dwReason ) == ERROR_MORE_DATA ) {
                    isFileLocked = ( nProcInfoNeeded != 0 );
                }
            }
            RmEndSession( dwSession );
        }
    
        return isFileLocked;
    }
    

答案 1 :(得分:1)

您需要使用GetLastError()来了解CreateFile()失败的原因,例如:

// this is requesting exclusive access to the file, so it will
// fail if the file is already open for any reason. That condition
// is detected by a sharing violation error due to conflicting
// sharing rights...

HANDLE fh = CreateFile("D:\\1.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (fh == INVALID_HANDLE_VALUE)
{
    switch (GetLastError())
    {
        case ERROR_PATH_NOT_FOUND:
        case ERROR_FILE_NOT_FOUND:
            MessageBox(NULL, "The file does not exist", "Error", 0);
            break;

        case ERROR_SHARING_VIOLATION:
            MessageBox(NULL, "The file is in use", "Error", 0);
            break;

        //...

        default:
            MessageBox(NULL, "Error opening the file", "Error", 0);
            break;
    }
}
else
{
    // the file exists and was not in use.
    // don't forget to close the handle...
    CloseHandle(fh);
}