移除由另一个进程锁定的文件
问题出现的原因:
1. 操作系统通常不会提供或者允许接管文件锁的所有权,除非得到原始锁的持有者的协助。
2. 无法轻易绕过操作系统的安全保证,尤其是在用户级别的测试代码中。
解决方法:
1. 如果需要得到原始所有者的协助,可以参考Windows的LockFileEx函数和DuplicateHandle函数。
2. 可以通过构建自定义的测试用的SqLite,使用被篡改的pager模块来模拟出问题的情况。
3. 最常用的解决方法是在测试环境中使用Mock对象来模拟特定的行为。在这种环境中,应用程序会在被要求的时候自愿释放SqLite连接,以便模拟操作系统或硬件故障,然后继续执行。
使用Mock对象比在黑盒环境中伪造有缺陷的文件系统驱动程序要容易得多。
参考链接:http://en.wikipedia.org/wiki/Software_testing#Destructive_testing
问题:Remove file locked by another process
原因:应用程序对文件的句柄未关闭。
解决方法:需要关闭应用程序对文件的句柄,然后重新打开文件。
参考链接:
- 解决方案示例代码:[Force close file by its path on Windows](https://stackoverflow.com/questions/25426627)
- 参考代码:[code.msdn.microsoft.com/windowsapps/CppFileHandle-03c8ea0b/sourcecode?fileId=52762&pathId=1613038731](https://code.msdn.microsoft.com/windowsapps/CppFileHandle-03c8ea0b/sourcecode?fileId=52762&pathId=1613038731)
文章标题:解决文件被另一个进程锁定的问题
在Windows操作系统中,有时候我们在删除文件时会遇到文件被另一个进程锁定的问题。下面的代码是一个解决这个问题的示例程序。
#include#include #include #include #include #include #include #include #include #define START_ALLOC 0x1000 #define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 #define SystemHandleInformation 0x10 typedef long(__stdcall *NtQSI)( ULONG SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); typedef struct _SYSTEM_HANDLE_ENTRY { ULONG OwnerPid; BYTE ObjectType; BYTE HandleFlags; USHORT HandleValue; PVOID ObjectPointer; ACCESS_MASK AccessMask; } SYSTEM_HANDLE_ENTRY, *PSYSTEM_HANDLE_ENTRY; int main(int argc, char *argv[]) { HMODULE hNtDll = NULL; NtQSI pNtQSI = NULL; PVOID pMem = NULL; ULONG allocSize = START_ALLOC; ULONG retVal = 0; // -------------------------------- ULONG hCount = 0; PSYSTEM_HANDLE_ENTRY hFirstEntry = NULL; // -------------------------------- ULONG i; hNtDll = LoadLibraryA("NTDLL.dll"); if (!hNtDll) return 1; pNtQSI = (NtQSI)GetProcAddress(hNtDll, "NtQuerySystemInformation"); if (!pNtQSI) { FreeLibrary(hNtDll); return 2; } pMem = malloc(allocSize); while (pNtQSI(SystemHandleInformation, pMem, allocSize, &retVal) == STATUS_INFO_LENGTH_MISMATCH) { pMem = realloc(pMem, allocSize *= 2); } hCount = *(ULONG*)pMem; hFirstEntry = (PSYSTEM_HANDLE_ENTRY)((PBYTE)pMem + 4); int pid = atoi(argv[1]); for (i = 0; i < hCount; ++i) if ((hFirstEntry[i].ObjectType == 30) && (hFirstEntry[i].OwnerPid == pid)) { HANDLE TargetHandleValueTemp = (HANDLE)hFirstEntry[i].HandleValue; HANDLE SourceProcHandleTemp = OpenProcess(PROCESS_DUP_HANDLE, FALSE, hFirstEntry[i].OwnerPid); char confirm ='n'; DuplicateHandle(SourceProcHandleTemp, (HANDLE)hFirstEntry[i].HandleValue, GetCurrentProcess(), &TargetHandleValueTemp, 0, FALSE, DUPLICATE_SAME_ACCESS); TCHAR Path[MAX_PATH]; DWORD dwret = GetFinalPathNameByHandle(TargetHandleValueTemp, Path, MAX_PATH, 0); if (!argv[2]) { _tprintf(TEXT("PID: %d\tFileHandle: %d\tThe final path is: %s\n"), hFirstEntry[i].HandleValue, TargetHandleValueTemp, Path); } else if (_tcsstr(Path, _T(argv[2]))) { _tprintf(TEXT("PID: %d\tFileHandle: %d\tThe final path is: %s\n\t Remove it? (y/n): "), hFirstEntry[i].HandleValue, TargetHandleValueTemp, Path); _flushall(); std::cin.get(confirm); if (confirm == 'y') DuplicateHandle(SourceProcHandleTemp, (HANDLE)hFirstEntry[i].HandleValue, GetCurrentProcess(), &TargetHandleValueTemp, 0, FALSE, DUPLICATE_CLOSE_SOURCE); } CloseHandle(SourceProcHandleTemp); CloseHandle(TargetHandleValueTemp); } free(pMem); FreeLibrary(hNtDll); }
这段代码可以解决Windows操作系统中文件被另一个进程锁定的问题。代码通过查询系统信息,找出所有打开的句柄,并根据进程ID和句柄类型判断是否为目标文件。如果是目标文件,则通过复制句柄并关闭源句柄的方式解除文件锁定。
调用示例:
program.exe
需要注意的是,这段代码是针对Windows 8.1版本的。如果使用其他版本的操作系统,可能需要根据实际情况修改代码中的`hFirstEntry[i].ObjectType`的值,尝试使用其他数值(如29、31、32)来代替30,以适配不同版本的系统。
这段代码使用了Windows的未公开API,因此描述和使用方法较为难以找到。