移除由另一个进程锁定的文件

8 浏览
0 Comments

移除由另一个进程锁定的文件

在测试应用程序稳定性时,我试图删除/损坏应用程序使用的数据库。操作系统是Windows,文件系统是NTFS,测试语言是C++。\n我需要的是将任何内容粘贴到数据库文件中或将其删除。但在运行期间,被测试的应用程序会锁定它。所以也许有人之前遇到过这种情况,可以给我/我们一个在测试代码中绕过此锁定的可能方法的示例吗?无论是理论还是源代码,我都会非常感激任何形式的帮助。

0
0 Comments

问题出现的原因:

1. 操作系统通常不会提供或者允许接管文件锁的所有权,除非得到原始锁的持有者的协助。

2. 无法轻易绕过操作系统的安全保证,尤其是在用户级别的测试代码中。

解决方法:

1. 如果需要得到原始所有者的协助,可以参考Windows的LockFileEx函数和DuplicateHandle函数。

2. 可以通过构建自定义的测试用的SqLite,使用被篡改的pager模块来模拟出问题的情况。

3. 最常用的解决方法是在测试环境中使用Mock对象来模拟特定的行为。在这种环境中,应用程序会在被要求的时候自愿释放SqLite连接,以便模拟操作系统或硬件故障,然后继续执行。

使用Mock对象比在黑盒环境中伪造有缺陷的文件系统驱动程序要容易得多。

参考链接:http://en.wikipedia.org/wiki/Software_testing#Destructive_testing

0
0 Comments

问题: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)

0
0 Comments

文章标题:解决文件被另一个进程锁定的问题

在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,因此描述和使用方法较为难以找到。

0