删除被其他进程锁定的文件
Remove file locked by another process
在测试应用程序稳定性时,我试图删除/损坏应用程序使用的数据库。操作系统是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
- 使用文件锁定的进程之间的条件变量
- 如何测试文件是否被锁定和/或只读而不打开?
- 我可以在C 中的Windows中读取一个文件,而无需锁定包含文件的文件夹
- 如何判断当前过程是否已经锁定文件
- C# 读取完全锁定的文本文件或读取 if 语句外部的输出
- Apache在PHP文件上保持文件锁定,直到关闭
- 在C++中锁定和解锁文件
- C++Ubuntu在终止时未释放锁定文件上的锁定
- 我可以在锁定文件后复制文件吗?
- 使用 boost::interprocess::file_lock 创建一个锁定的文件
- 锁定文件,避免使用相同的过程以访问两次
- 正在为编写者和读者寻找最佳的增强文件锁定机制
- 我创建锁定文件的功能导致访问冲突
- 如果原始文件被锁定,是否可以从装载点读取
- 如何确保我的进程永远不会将另一个进程锁定在文件之外
- FindFirstChangeNotification 锁定父文件夹
- 视窗C++ 锁定内存中的文件
- 正在释放Qt中的文件锁定
- C++中的文件锁定用于同时读取和写入锁定
- C++:线程和进程之间的文件锁定