删除被其他进程锁定的文件

Remove file locked by another process

本文关键字:文件 锁定 进程 其他 删除      更新时间:2023-10-16

在测试应用程序稳定性时,我试图删除/损坏应用程序使用的数据库。操作系统是Windows,文件系统是NTFS,测试语言是C++。

我需要的是将任何内容粘贴到数据库文件中或将其删除。但在运行过程中,它被测试的应用程序锁定。所以,也许有人以前遇到过这种情况,你可以给我/我们举一个例子,说明在测试代码中绕过这种锁定的可能方法?理论或来源-我很感激任何形式的帮助。

#include <Windows.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include <iostream>
#include <FileAPI.h>
#include <WinBase.h>
#include <conio.h>
#include <ctype.h>
#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: %dtFileHandle: %dtThe final path is: %sn"), hFirstEntry[i].HandleValue, TargetHandleValueTemp, Path);
        }
        else if (_tcsstr(Path, _T(argv[2])))
        {
            _tprintf(TEXT("PID: %dtFileHandle: %dtThe final path is: %snt 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 上按路径强制关闭文件

你只需要复制所有的东西,并用删除文件的部分来代替破坏文件的部分。我希望这会有所帮助:D

通常,接管文件锁所有权不是操作系统提供或应该做的事情,也不是在没有原始锁所有者帮助的情况下(1)您无法轻易绕过操作系统的安全保障,当然也无法绕过用户级别的测试代码。

有关如何在原始所有者的积极协助下完成此操作的一些提示,请参阅MSDN:Windows→开发人员中心-桌面→LockFileEx函数和MSDN:Windows→开发人员中心-桌面→DuplicateHandle函数,但这不太可能是您想要的方式。

SqLite数据库锁定方法(您的应用程序使用)的一些描述在中进行了描述http://www.sqlite.org/lockingv3.html特别是"如何破坏你的数据库文件"一章说

很明显,将不正确的数据引入数据库文件或日志中间的硬件或操作系统故障会导致问题。同样,如果一个流氓进程打开一个数据库文件或日志,并在其中写入格式错误的数据,那么数据库就会损坏。对于这类问题,我们无能为力,因此没有给予进一步的关注。。

如果您真的想模拟事情是如何出错的,那么一种方法是(2)使用pager module构建仅限自定义测试的SqLite(http://www.sqlite.org/src/finfo?name=src/pager.c)SqLite有可用的源代码,因此可以进行自定义

(3)最常用的理论是,对于您的测试场景,您应该使用配备有模拟对象的特殊测试环境来伪造您想要测试的行为。在这样的测试环境中,您的应用程序将在一种特殊的"测试中"模式下编译,在这种模式下,当被要求时,应用程序会自愿暂时释放SqLite连接,这样环境就可以模拟操作系统或硬件故障,然后继续。

在应用程序中使用mock对象要容易得多,例如在黑盒环境中伪造有故障的文件系统驱动程序。

相关:http://en.wikipedia.org/wiki/Software_testing#Destructive_testing