在Windows上使用C++锁定文件

6

我有一个从文件中读写的程序,并且我想将该文件锁定以防止应用程序的其他实例访问。 我该怎么做(在c++ visual studio 2003中)? 我尝试使用_locking()函数,但是在同一实例中尝试读/写文件时,我自己也无法访问该文件。 我知道有一个LockFile()选项,但不知道如何正确设置它。 请帮助我。


当使用 fstream/File* 时,如何获取文件句柄?我尝试使用 createfile(),但它仍然会锁定该文件,在这种情况下怎么办? - sofsr
有没有办法将createfile的句柄转换为fstream? - sofsr
@Sofsr:看看这个问题:https://dev59.com/63RA5IYBdhLWcg3wwwvD - Casebash
3个回答

16
您可以简单地使用Win32 API CreateFile,然后指定不共享权限。这将确保没有其他进程可以访问该文件。
dwShareMode DWORD 指定您想要的共享类型,例如 GENERIC_READ。如果您指定 0,则表示不应授予共享权限。
示例:
HANDLE hFile = CreateFile(_T("c:\\file.txt"), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);

如果你只想锁定文件的某个部分,可以使用LockFileLockFileEx

示例:

 //Lock the first 1024 bytes
 BOOL bLocked = LockFile(hFile, 0, 0, 1024, 0);

如果需要在其他平台上进行锁定,请参见我的这篇文章


如果文件已经存在,您想锁定整个文件和传入的附加内容怎么办? - Sandburg

1

在网上搜索了一段时间后,我没有找到任何好的例子。

这里有两个调用CreateFile的示例,旨在锁定文件的进程生命周期... 我将其与使用CreateMutex进行全局命名互斥的CLimitSingleInstance一起使用。

第一个CreateFile调用尝试打开它,第二个调用在必要时创建它。 我有一个更彻底的实现。我在Qt中实现了它,因此使用qCritical()而不是std::cout,并使用QDir::tempPath()而不是其他方式获取它。

class SingleInstance
{
protected:
    DWORD  m_dwLastError;
    HANDLE m_hFile;
public:
    SingleInstance(const char *strMutexName) {  }

    bool attemptToLockTempFile()
    {
      QString lockFile = QDir::tempPath() + "/My.exe.lock";
      m_hFile = CreateFileA(lockFile.toLocal8Bit().data(), GENERIC_READ, 0, 
                                NULL, OPEN_EXISTING, 0, NULL);
      DWORD dwLastError = GetLastError();
      if(m_hFile != NULL && m_hFile != INVALID_HANDLE_VALUE)
      {
          return true;
      }
      else
      {
          if(dwLastError == ERROR_FILE_NOT_FOUND )
          {
              m_hFile = CreateFileA(lockFile.toLocal8Bit().data(), GENERIC_READ, 
                                        0, NULL, CREATE_NEW, 0, NULL);
              dwLastError = GetLastError();

              if(m_hFile != NULL && m_hFile != INVALID_HANDLE_VALUE)
              {
                  return true;
              }
              else if(dwLastError == ERROR_SHARING_VIOLATION)
              {
                  qCritical() << "Sharing Violation on My.exe.lock";
              }
              else
              {
                  qCritical() << "Error reading" << "My.exe.lock" << "-" << dwLastError;
              }
          }
          else if(dwLastError == ERROR_SHARING_VIOLATION)
          {
              qCritical() << "Sharing Violation on My.exe.lock";
          }
          else
          {
              qCritical() << "Unable to obtain file lock -" << dwLastError;
          }
          return false;
      }
    }

    ~SingleInstance()
    {
        if ( m_hFile != NULL && m_hFile != INVALID_HANDLE_VALUE)
        {
            ::CloseHandle(m_hFile); //Do as late as possible.
            m_hFile = NULL;
        }
    }
}

这是你在主函数顶部应该有的内容:

SingleInstance g_SingleInstanceObj(globalId_QA);

// Makes sure that the program doesn't run if there is another 
// instance already running
if (g_SingleInstanceObj.IsAnotherInstanceRunning())
{
    return 0;
}

1

您需要使用LockFileEx()(独占文件锁定)。请参考Secure Programming Cookbook for C and C++中的此讨论


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接