如何监视文件上的锁定以查看它何时被释放? [C ++]

时间:2009-05-18 20:06:34

标签: c++ winapi file

我正在寻找一种在非托管 c ++中创建程序的方法,该方法等待文件解锁(因为它已不再使用)并且执行某些操作。我没有找到如何做到这一点的运气,任何帮助将不胜感激!

更新:我可能已回答了我自己的问题,请参阅下文并告诉我您的想法......

更新:真正重要的是文件是可写的,如果它仍在使用中并不重要。

5 个答案:

答案 0 :(得分:2)

这样的事情会在不浪费cpu周期的情况下等待。

HANDLE h = FindFirstChangeNotification("C:\Path to folder holding file", FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE);

while(true)
{
    if (CheckLockFile("C:\Path to file"))
    {
        // Do something
        break;
    }

    WaitForSingleObject(h, APPROPRIATE_TIMEOUT_VALUE);
    FindNextChangeNotification(h);
}

bool CheckLockFile(char* FilePath)
{
    HANDLE fh = CreateFile(FilePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0,NULL);
    if (fh == INVALID_HANDLE_VALUE)
    {
        return false; 
    }
    CloseHandle(fh);

    return true;
}

这假设对文件具有锁定的应用程序将其打开以进行写入。

答案 1 :(得分:1)

创建一个每5秒调用::CreateFile()的循环,直到成功为止。在dwShareMode参数中传递0,以确保没有其他进程打开文件。

答案 2 :(得分:0)

这是我的问题的一个可能的解决方案,有人看到这个问题吗?

#include <iostream>
#include <fstream>
#include <windows.h>
using namespace std;
void main(int argc, char ** argv) {
    if (argc < 2 || argc > 2) {
        return;
    }

    ofstream myfile;
    myfile.open(argv[1], ios_base::app);
    while (!myfile.is_open()) { Sleep(100); myfile.open(argv[1], ios_base::app); }
    myfile.close();

    // file should now be unlocked..
}

再次感谢!

更新:将代码更改为更完整。

答案 3 :(得分:0)

听起来你想在另一个程序释放锁之后访问该文件。 UNIX(和Cygwin)只需锁定文件即可为您提供此行为。

使用ScopeGuard之类的内容可能会使File_locker变得不必要,但如果您不使用ScopeGuard,请执行以下操作:

UNIX:

#include <stdexcept>
#include <string>
#include "sys/file.h" //flock
#include "sys/fcntl.h" //open

class File_locker {
    int file_descriptor;
  public:
    File_locker(std::string filename)
    {
        // you can use errno to determine why the open/flock failed,
        // but this is a demo, not production code

        file_descriptor = ::open(filename.c_str(), O_RDWR);
        if (file_descriptor < 0)
            throw std::runtime_error((std::string("unable to open file ")
                + filename).c_str());
        if (::flock(file_descriptor, LOCK_EX)) {
            ::close(file_descriptor);
            throw std::runtime_error((std::string("unable to flock file ")
                + filename).c_str());
        }
    }
    ~File_locker()
    {
        ::flock(file_descriptor, LOCK_UN); // don't forget to unlock
        ::close(file_descriptor);
    }
};

在Windows中,您似乎必须轮询该文件。

视窗:

#include <string>
#include "windows.h"

class File_locker {
    HANDLE file_handle;
    static const int MAX_TRIES = 10;
    static const int SLEEP_INTERVAL = 500;

  public:
    File_locker(std::string filename)
    {
        // you can use GetLastError() to determine why the open failed,
        // but this is a demo, not production code
        for (int i = 0; i < MAX_TRIES; ++i) {
            file_handle = ::CreateFile(filename.c_str(),
                                       GENERIC_READ | GENERIC_WRITE,
                                       0,
                                       NULL,
                                       OPEN_EXISTING,
                                       FILE_ATTRIBUTE_NORMAL,
                                       NULL);
            if (file_handle != INVALID_HANDLE_VALUE)
                return;
            ::Sleep(SLEEP_INTERVAL);
            }
            throw std::runtime_error((std::string("unable to open file ")
                + filename).c_str());
    }
    ~File_locker()
    {
        ::CloseHandle(file_handle);
    }
};

像这样使用它:

#include <fstream>
#include <stdexcept>

// .. define File_locker, as above

int main()
{
    try {
        File_locker fl("filename.txt");
        // once fl is constructed, nobody else has the file locked
        std::fstream file("filename.txt");
        // ...
        return 0;
    }
    catch (std::runtime_error& ex)
    {
        // just bail
        return 1;
    }
}

答案 4 :(得分:-1)

只需使用系统锁定文件通知