我有一个从文件中读写的程序,并且我想将该文件锁定以防止应用程序的其他实例访问。 我该怎么做(在c++ visual studio 2003中)? 我尝试使用_locking()函数,但是在同一实例中尝试读/写文件时,我自己也无法访问该文件。 我知道有一个LockFile()选项,但不知道如何正确设置它。 请帮助我。
我有一个从文件中读写的程序,并且我想将该文件锁定以防止应用程序的其他实例访问。 我该怎么做(在c++ visual studio 2003中)? 我尝试使用_locking()函数,但是在同一实例中尝试读/写文件时,我自己也无法访问该文件。 我知道有一个LockFile()选项,但不知道如何正确设置它。 请帮助我。
HANDLE hFile = CreateFile(_T("c:\\file.txt"), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
如果你只想锁定文件的某个部分,可以使用LockFile或LockFileEx。
示例:
//Lock the first 1024 bytes
BOOL bLocked = LockFile(hFile, 0, 0, 1024, 0);
在网上搜索了一段时间后,我没有找到任何好的例子。
这里有两个调用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;
}