आप मूल रूप से दो तरह से
आसान तरीका
है
आप Windows Vista का उपयोग कर रहे या नए IFileIsInUse
इंटरफ़ेस
मुश्किल रास्ता
कोशिश आप एक विधि विंडोज एक्सपी, विस्टा, 7 और इतने पर के साथ संगत की जरूरत है, तो। तो आप NtQuerySystemInformation, NtQueryInformationFile और NtQueryObject फ़ंक्शंस का उपयोग करें।
ये आगे बढ़ने के लिए चरणों
- कॉल NTQuerySystemInformation अप्रलेखित SystemHandleInformation ($10) मूल्य गुजर हैंडल
- की सूची प्राप्त करने जो फ़ाइलें हैं (केवल ObjectType = 28 के लिए) तो हैंडल की सूची पर कार्रवाई कर रहे हैं।
PROCESS_DUP_HANDLE
- साथ कॉल OpenProcess तो DuplicateHandle फोन के लिए फाइल करने के लिए एक
real
संभाल मिलता है।
- NtQueryInformationFile और NtQueryObject फ़ंक्शंस का उपयोग करके हैंडल के लिए संबद्ध फ़ाइल नाम का नाम प्राप्त करें।
नोट 1: इस विधि का मुश्किल हिस्सा एक हैंडल में आधारित फ़ाइल नाम को हल है। फ़ंक्शन NtQueryInformationFile
कुछ परिदृश्यों (सिस्टम हैंडल और अन्य) में लटकता है, पूरे एप्लिकेशन को लटकने से रोकने के लिए एक वर्कअराउंड फ़ंक्शन को एक अलग थ्रेड से कॉल करता है।
नोट 2: हैंडल के फ़ाइल नाम को हल करने के लिए GetFileInformationByHandleEx और GetFinalPathNameByHandle जैसे अन्य फ़ंक्शंस मौजूद हैं। लेकिन दोनों मौजूद हैं क्योंकि Windows viste इस तरह के मामले में डी 0 बेहतर उपयोग IFileIsInUse
है।
डेल्फी 2007, एक्सई 2 और विंडोज एक्सपी और 7 में परीक्षण किए गए इस नमूना अनुप्रयोग की जांच करें। यहां से आप अपनी समस्या को हल करने के लिए कुछ विचार ले सकते हैं।
नोट: फ़ंक्शन GetProcessIdUsingFile
केवल फ़ाइलों का नाम (पथ नहीं) की तुलना करता है।
{$APPTYPE CONSOLE}
uses
Windows,
SysUtils;
const
SystemHandleInformation = $10;
STATUS_SUCCESS = $00000000;
FileNameInformation = 9;
ObjectNameInformation = 1;
type
SYSTEM_HANDLE=packed record
uIdProcess:ULONG;
ObjectType:UCHAR;
Flags :UCHAR;
Handle :Word;
pObject :Pointer;
GrantedAccess:ACCESS_MASK;
end;
SYSTEM_HANDLE_ARRAY = Array[0..0] of SYSTEM_HANDLE;
SYSTEM_HANDLE_INFORMATION=packed record
uCount:ULONG;
Handles:SYSTEM_HANDLE_ARRAY;
end;
PSYSTEM_HANDLE_INFORMATION=^SYSTEM_HANDLE_INFORMATION;
NT_STATUS = Cardinal;
PFILE_NAME_INFORMATION = ^FILE_NAME_INFORMATION;
FILE_NAME_INFORMATION = packed record
FileNameLength: ULONG;
FileName: array [0..MAX_PATH - 1] of WideChar;
end;
PUNICODE_STRING = ^TUNICODE_STRING;
TUNICODE_STRING = packed record
Length : WORD;
MaximumLength : WORD;
Buffer : array [0..MAX_PATH - 1] of WideChar;
end;
POBJECT_NAME_INFORMATION = ^TOBJECT_NAME_INFORMATION;
TOBJECT_NAME_INFORMATION = packed record
Name : TUNICODE_STRING;
end;
PIO_STATUS_BLOCK = ^IO_STATUS_BLOCK;
IO_STATUS_BLOCK = packed record
Status: NT_STATUS;
Information: DWORD;
end;
PGetFileNameThreadParam = ^TGetFileNameThreadParam;
TGetFileNameThreadParam = packed record
hFile : THandle;
Result : NT_STATUS;
FileName : array [0..MAX_PATH - 1] of AnsiChar;
end;
function NtQueryInformationFile(FileHandle: THandle;
IoStatusBlock: PIO_STATUS_BLOCK; FileInformation: Pointer;
Length: DWORD; FileInformationClass: DWORD): NT_STATUS;
stdcall; external 'ntdll.dll';
function NtQueryObject(ObjectHandle: THandle;
ObjectInformationClass: DWORD; ObjectInformation: Pointer;
ObjectInformationLength: ULONG;
ReturnLength: PDWORD): NT_STATUS; stdcall; external 'ntdll.dll';
function NtQuerySystemInformation(SystemInformationClass: DWORD; SystemInformation: Pointer; SystemInformationLength: ULONG; ReturnLength: PULONG): NT_STATUS; stdcall; external 'ntdll.dll' name 'NtQuerySystemInformation';
function GetFileNameHandleThr(Data: Pointer): DWORD; stdcall;
var
dwReturn: DWORD;
FileNameInfo: FILE_NAME_INFORMATION;
ObjectNameInfo: TOBJECT_NAME_INFORMATION;
IoStatusBlock: IO_STATUS_BLOCK;
pThreadParam: TGetFileNameThreadParam;
begin
ZeroMemory(@FileNameInfo, SizeOf(FILE_NAME_INFORMATION));
pThreadParam := PGetFileNameThreadParam(Data)^;
Result := NtQueryInformationFile(pThreadParam.hFile, @IoStatusBlock, @FileNameInfo, MAX_PATH * 2, FileNameInformation);
if Result = STATUS_SUCCESS then
begin
Result := NtQueryObject(pThreadParam.hFile, ObjectNameInformation, @ObjectNameInfo, MAX_PATH * 2, @dwReturn);
if Result = STATUS_SUCCESS then
begin
pThreadParam.Result := Result;
WideCharToMultiByte(CP_ACP, 0, @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength - ObjectNameInfo.Name.Length], ObjectNameInfo.Name.Length, @pThreadParam.FileName[0], MAX_PATH, nil, nil);
end
else
begin
pThreadParam.Result := STATUS_SUCCESS;
Result := STATUS_SUCCESS;
WideCharToMultiByte(CP_ACP, 0, @FileNameInfo.FileName[0], IoStatusBlock.Information, @pThreadParam.FileName[0], MAX_PATH, nil, nil);
end;
end;
PGetFileNameThreadParam(Data)^ := pThreadParam;
ExitThread(Result);
end;
function GetFileNameHandle(hFile: THandle): String;
var
lpExitCode: DWORD;
pThreadParam: TGetFileNameThreadParam;
hThread: THandle;
begin
Result := '';
ZeroMemory(@pThreadParam, SizeOf(TGetFileNameThreadParam));
pThreadParam.hFile := hFile;
hThread := CreateThread(nil, 0, @GetFileNameHandleThr, @pThreadParam, 0, PDWORD(nil)^);
if hThread <> 0 then
try
case WaitForSingleObject(hThread, 100) of
WAIT_OBJECT_0:
begin
GetExitCodeThread(hThread, lpExitCode);
if lpExitCode = STATUS_SUCCESS then
Result := pThreadParam.FileName;
end;
WAIT_TIMEOUT:
TerminateThread(hThread, 0);
end;
finally
CloseHandle(hThread);
end;
end;
//get the pid of the process which had open the specified file
function GetProcessIdUsingFile(const TargetFileName:string): DWORD;
var
hProcess : THandle;
hFile : THandle;
ReturnLength: DWORD;
SystemInformationLength : DWORD;
Index : Integer;
pHandleInfo : PSYSTEM_HANDLE_INFORMATION;
hQuery : THandle;
FileName : string;
begin
Result:=0;
pHandleInfo := nil;
ReturnLength := 1024;
pHandleInfo := AllocMem(ReturnLength);
hQuery := NTQuerySystemInformation(DWORD(SystemHandleInformation), pHandleInfo, 1024, @ReturnLength);
if ReturnLength<>0 then
begin
FreeMem(pHandleInfo);
SystemInformationLength := ReturnLength;
pHandleInfo := AllocMem(ReturnLength+1024);
hQuery := NTQuerySystemInformation(DWORD(SystemHandleInformation), pHandleInfo, SystemInformationLength, @ReturnLength);//Get the list of handles
end
else
RaiseLastOSError;
try
if(hQuery = STATUS_SUCCESS) then
begin
for Index:=0 to pHandleInfo^.uCount-1 do
if pHandleInfo.Handles[Index].ObjectType=28 then
begin
hProcess := OpenProcess(PROCESS_DUP_HANDLE, FALSE, pHandleInfo.Handles[Index].uIdProcess);
if(hProcess <> INVALID_HANDLE_VALUE) then
begin
try
if not DuplicateHandle(hProcess, pHandleInfo.Handles[Index].Handle,GetCurrentProcess(), @hFile, 0 ,FALSE, DUPLICATE_SAME_ACCESS) then
hFile := INVALID_HANDLE_VALUE;
finally
CloseHandle(hProcess);
end;
if (hFile<>INVALID_HANDLE_VALUE) then
begin
try
FileName:=GetFileNameHandle(hFile);
finally
CloseHandle(hFile);
end;
end
else
FileName:='';
//Writeln(FileName);
if CompareText(ExtractFileName(FileName), TargetFileName)=0 then
Result:=pHandleInfo.Handles[Index].uIdProcess;
end;
end;
end;
finally
if pHandleInfo<>nil then
FreeMem(pHandleInfo);
end;
end;
function SetDebugPrivilege: Boolean;
var
TokenHandle: THandle;
TokenPrivileges : TTokenPrivileges;
begin
Result := false;
if OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, TokenHandle) then
begin
if LookupPrivilegeValue(nil, PChar('SeDebugPrivilege'), TokenPrivileges.Privileges[0].Luid) then
begin
TokenPrivileges.PrivilegeCount := 1;
TokenPrivileges.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
Result := AdjustTokenPrivileges(TokenHandle, False,
TokenPrivileges, 0, PTokenPrivileges(nil)^, PDWord(nil)^);
end;
end;
end;
begin
try
SetDebugPrivilege;
Writeln('Processing');
Writeln(GetProcessIdUsingFile('MyFile.txt'));
Writeln('Done');
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
Readln;
end.
आप WMI और 'cim_datafile' मेरा मानना है कि के साथ ऐसा कर सकते हैं। लेकिन मुझे डब्लूएमआई के बारे में कुछ नहीं पता है। हालांकि, मुझे उम्मीद है कि यहां अन्य विशेषज्ञों में से एक जो डब्लूएमआई में विशेषता रखते हैं, आपकी मदद कर सकेंगे! –
विंडोज के किस संस्करण को आपको समर्थन देने की आवश्यकता है? यदि Windows Vista ऊपर है तो ['this post'] देखें (http://blog.delphi-jedi.net/2010/11/14/is-file-in-use/), यह [' IFileIsInUse'] का उपयोग करता है (http://msdn.microsoft.com/en-us/library/bb775874%28VS.85%29.aspx) इंटरफ़ेस। – TLama
हम अपने सॉफ्टवेयर में http://technet.microsoft.com/en-us/sysinternals/bb896655 का उपयोग करते हैं। उपयोग में फ़ाइल रखने वाली प्रक्रिया को हैंडल.एक्सई की जानकारी का उपयोग करके लॉग किया गया है जो SysInternals (अब माइक्रोसॉफ्ट के स्वामित्व में) द्वारा एक निःशुल्क टूल है। –