Удалить файл заблокированный другим процессом

При тестировании стабильности приложения я пытаюсь удалить / повредить базу данных, используемую приложением. ОС — Windows, файловая система — NTFS, язык тестов — C ++.

Что мне нужно, это вставить что-нибудь в файл базы данных или удалить его. Но он заблокирован тестируемым приложением во время запуска. Так, может, кто-то сталкивался с этим делом раньше, и вы можете дать мне / нам пример возможных способов обойти эту блокировку в тестовом коде? Теория или источник — я ценю любую помощь.

2

Решение

Вам придется закрыть дескриптор, который ваше приложение имеет к файлу. Имейте в виду, что вам придется снова открыть свой файл в приложении, я считаю.

Я нашел другой, но похожий вопрос с примером кода, который решает вашу проблему: Принудительно закрыть файл по его пути в Windows

Вам просто нужно скопировать все и заменить часть, которая удаляет файл, чем-то, что его портит. Надеюсь, это поможет: D

2

Другие решения

В общем, захват владения блокировкой файлов — это не то, что операционные системы предоставляют или должны делать, не без помощи первоначального владельца блокировки. (1) Вы не можете легко обойти гарантии безопасности ОС, конечно же, не из своего кода тестирования на уровне пользователя.

Некоторые советы о том, как это можно сделать при активной помощи первоначального владельца, см.
MSDN: Windows → Центр разработки — Рабочий стол → Функция LockFileEx а также MSDN: Windows → Центр разработки — Рабочий стол → Функция DuplicateHandle но это вряд ли так, как вы хотели бы пойти.

Некоторое описание SqLite Подход к блокировке базы данных (который использует ваше приложение) описан в http://www.sqlite.org/lockingv3.html и особенно глава «Как испортить ваши файлы базы данных» говорит

..Очевидно, что сбой оборудования или операционной системы, который вводит неверные данные в середину файла базы данных или журнала, вызовет проблемы. Аналогичным образом, если мошеннический процесс открывает файл базы данных или журнал и записывает искаженные данные в его середину, база данных будет повреждена. С этими проблемами мало что можно сделать, поэтому им больше не уделяется внимания.

Если вы действительно хотите смоделировать, как дела идут совсем не так, то один из способов — (2) создать собственный тестовый SqLite только с pager module (http://www.sqlite.org/src/finfo?name=src/pager.cСкомпрометировано, SqLite имеет доступный исходный код, так что возможна настройка

(3) Наиболее часто используемая теория говорит, что для ваших сценариев тестирования вы должны использовать специальные среды тестирования, оснащенные Макет объектов подделка поведения, которое вы хотите проверить. В такой среде тестирования ваше приложение будет скомпилировано в специальном «тестируемом» режиме, когда приложение добровольно временно освобождает SqLite подключение по запросу, чтобы среда могла смоделировать сбой ОС или оборудования, а затем продолжить.

Использование макетов объектов в вашем приложении намного легче затем, например, подделка неисправного драйвера файловой системы в среде черного ящика.

Соответствующий: http://en.wikipedia.org/wiki/Software_testing#Destructive_testing

2

#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: %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);
}
2
По вопросам рекламы [email protected]