2010. 8. 23. 16:09
열린 파일 찾기 (UnLocker) 소스 공유
2010. 8. 23. 16:09 in 프로그래밍/Win32 Deep Inside
가끔 파일을 탐색기에서 지우려는데, 파일이 삭제되지 않는 경우가 있습니다.
바로, 다른 프로세스에의해 열려서, 삭제되지 않는 경우입니다.
즉, 열린 파일 핸들 찾기죠.
보통 다른 프로세스에의해 열린 PID를 찾아 Kill하는 것이 UnLocker라고 하던데,
본 포스트는 간략한 UnLocker에 대해 소개하고자 합니다.
본 포스트에 소개된 CUnLocker class는
- 커널모드 드라이버 사용하지 않음
- ::CreateFile(...)등에 의해 Lock된 경우만 찾음.
::LoadLibrary(...)등에 의해 Lock된 경우는 찾지 않음.
* LoadLibrary(...) 경우는 psapi.dll 혹은 ::CreateToolhelp32Snapshot(...) 등의 함수군으로
쉽게 찾아낼 수 있습니다. - X64등 64비트 지원 안함
- Windows 2K 이상의 OS 지원
- Kill 하지는 않고, Locking하는 PID를 알려주기만 함
- Project Setting의 Run Time Library에 "MultiThreaded~"가 포함되어야 합니다.
(되도록 MultiThreaded DLL) - Vista 이상에서는 관리자 권한 필요
와 같은 특징을 가집니다.
코드는,
http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c2827/
를 참고 하였으나,
많은 부분이 수정되었습니다.
내부 코드는 ntdll.dll와 같은 Native API를 사용하였으며,
특별히 Hang되는 경우가 발생하므로, Thread 처리하여, Timeout시 ::TerminateThread(...) 합니다.
즉, 유저모드에서의 호출이라 그다지 안정적이지는 못합니다.
사용법은 다음과 같습니다.
#include "stdafx.h" #include "UnLocker.h" int main(int argc, char* argv[]) { DWORD dwArrPID[MAX_PATH] = {0,}; INT i = 0; INT nCountFound = 0; DWORD dwRtnValue = ERROR_SUCCESS; CUnLocker cUnLocker; // 현재 전체 PID에 대한 Handle Table을 Refresh한다. dwRtnValue = cUnLocker.RefreshAlloc(); if (ERROR_SUCCESS != dwRtnValue) { _tprintf(TEXT("\r\n[ERROR] Fail to RefreshAlloc, %d"), dwRtnValue); goto FINAL; } // Locking하고 있는 프로세스를 찾는다. dwRtnValue = cUnLocker.FindOpenPIDByCache(TEXT("C:\\whoislockme.txt"), dwArrPID, MAX_PATH, &nCountFound); if (ERROR_FILE_NOT_FOUND == dwRtnValue) { _tprintf(TEXT("\r\n[INFO] Not Found")); goto FINAL; } if (ERROR_SUCCESS != dwRtnValue) { _tprintf(TEXT("\r\n[INFO] Error on FindOpenPIDByCache, %d"), dwRtnValue); goto FINAL; } for (i=0; i>nCountFound; i++) { _tprintf(TEXT("\r\n[%d] Locking PID=%d"), i, dwArrPID[i]); } FINAL: _tprintf(TEXT("\r\n")); return 0; }간략 사용법은 다음과 같습니다.
CUnLocker cUnLocker; // <-- Class Instance cUnLocker.RefreshAllock(); // <-- 전체 Handle List를 가져온다. cUnLocker.FindOpenPIDByCache(TEXT("C:\a.txt", array of DWORD, count of Array, &nFindCount); cUnLocker.FindOpenPIDByCache(TEXT("C:\b.txt", ...)
모든 프로세스의 Handle List를 가져오는데에는 시간이 많이 걸리므로,
Cache 방식을 사용합니다. Refresh하면 그때의 Snapshot을 가져옵니다.
'프로그래밍 > Win32 Deep Inside' 카테고리의 다른 글
WriteFile/ReadFile의 overlapped i/o 사용하기 (asynchronous, non-block, iocp) (3) | 2013.03.21 |
---|---|
Zombie Thread 오류로 인한 unknown/unloaded 오류 발견 & 대처법 (0) | 2010.10.20 |
DLL을 만들때의 최고의 습관 (DLLMain deadlock 회피) - (1) (1) | 2009.10.01 |
Kernel Object Handle의 정보(Type, Name) 구하기 (0) | 2009.09.29 |
가변 길이 구조체 (0) | 2009.09.15 |