利用Windows API判断文件共享锁定状态
新疆塔里木农垦大学农业工程学院 陈立平 01-11-23 下午 01:59:05
--------------------------------------------------------------------------------
一、概述
锁是操作系统为实现数据共享而提供的一种安全机制,它使得不同的应用程序,不同的计算机之间可以安全有效地共享和交换数据。要保证安全有效地操作共享数据,必须在相应的操作前判断锁的类型,然后才能确定数据是否可读或可写,从而为开发出健壮的程序提供切实依据。 同样,在Windows中,文件可以共享模式打开,它也涉及到锁的操作问题。根据Windows中文件共享时加锁范围的大小,锁可分为全局锁和局部锁;全局锁以锁定文件全部内容为特征,而局部锁以锁定文件的局部内容为特征,且文件的锁定区域不可重复。根据Windows中文件共享时锁的操作权限分类,锁可分为:读锁,写锁,读写锁(可读可写,全局锁)。 利用上述文件中锁的区域不可重复的特性,我们可尝试给指定文件加一全局锁。若加锁成功,说明指定文件未被其它进程锁定;否则,说明有其它进程锁定了该文件。这里,我们利用两个Windows Api文件操作函数:OpenFile和CreateFile来实现锁定状态的判断。
二、实现方法 1. OpenFile函数使用说明 函数原型:function OpenFile(const lpFileName: LPCSTR; var lpReOpenBuff: TOFStruct; uStyle: UINT): HFILE; stdcall; 函数功能:以不同方式打开文件的操作(为兼容16位Windows程序保留的函数)。建议 Windows下使用CreateFile函数。 参数说明:lpFileName: 要打开文件的名称 lpReOpenBuff: 变量指针,用于存储文件被首次打开时接收信息。 UStyle: 打开文件的常量类型。 常量名 意义
Of_Create 创建文件
Of_Delete 删除指定文件
Of_Exist 打开文件以验证其存在否?存在,返回一无效句柄;否则,返回负数
Of_Parse 填充lpReOpenBuff内容,但不进行任何操作
Of_Prompt 如存在不存在,则显示一有重试和取消按钮的消息框
Of_Read 只读方式打开
Of_ReadWrite 读写方式打开
Of_ReOpen 打开lpReOpenBuff内指定的文件,而不依据lpFileName
Of_Search 强迫Windows查找文件---即使指定了文件路径
Of_Share_Compat 文件可由多个程序多次打开
Of_Share_Deny_None 共享打开
Of_Share_Deny_Read 禁止其它程序读该文件
Of_Share_Deny_Write 禁止其它程序写该文件
Of_Share_Exclusive 独占方式打开文件,其它程序不得再打开该文件
Of_Write 只写方式打开
返回值:成功,返回值为文件句柄(但可能无效,如:Of_Exist);出错,返回HFile_Error。 2. CreateFile函数使用说明 函数原型:function CreateFile(lpFileName: PChar; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall; 函数功能:以不同方式打开文件的操作,还可操作管道、邮槽、通信服务、设备以及控 制台等。 参数说明: lpFileName: 要打开文件的名称 dwDesiredAccess:期望存取模式 取值 0:只允许获取一个设备的相关信息。 Generic_Read:只允许读设备 Generic_Write:只允许写设备(二者可组合使用)。 dwShareMode:共享模式。 取值 0: 不共享。 File_Share_Read和/或File_Share_Write:共享读和/或写。 lpSecurityAttributes: 定义文件安全特性的指针(前提:操作系统支持)。 DwCreationDisposition: 打开和创建文件方式。 取值 Create_New: 总创建新文件,如文件已存在,则出错。 Create_Always: 总创建新文件(会覆盖旧文件)。 Open_Existing: 打开已存在的文件,若文件不存在,则出错。 Open_Always: 总打开文件,如不存在,则创建。 dwFlagsAndAttributes: 要打开文件的标志和属性(如:隐藏,系统等)。 一般用File_Attribute_Normal,默认属性。 hTemplateFile::模板文件句柄。 若非0则指定一个文件句柄;否则,新文件将从这个文件复制 扩展属性。 返回值:成功,返回值为文件句柄;出错,返回Invalid_Handle_Value。
3。程序实现 利用上述两个函数,我们可编写程序判断某文件是否正在被其它进程锁定,以下为详细代码。 //利用OpenFile Api函数判断 function FileLocked(Fn: string): Boolean; var I : Integer; Struct: TOfStruct; Style: Cardinal; Hdl: Hfile; Drive: String; begin Style := OF_Share_Exclusive; //排它方式打开 Drive := UpperCase(Fn[1]); Struct.fFixedDisk := Ord(Drive <> 'A'); //判断是否是硬盘 Struct.cBytes := SizeOf(Struct); For I := 1 to Length(Fn) do Struct.szPathName[I-1] := Fn[I]; Struct.szPathName[I] := Chr(0); //填充文件名 Hdl := OpenFile(Pchar(Fn), Struct, Style); if Hdl = HFILE_ERROR then begin Result := True; //文件被锁定 Showmessage(SysErrorMessage(GetLastError)); //显示错误原因 end else Result := False; end;
//利用CreateFile Api函数判断 function LockedFile(Fn: string): Boolean; var AFile: THandle; SecAtrrs: TSecurityAttributes; begin FillChar(SecAtrrs, SizeOf(SecAtrrs), #0); SecAtrrs.nLength := SizeOf(SecAtrrs); //结构体长度 SecAtrrs.lpSecurityDescriptor := nil; //安全描述 SecAtrrs.bInheritHandle := True; //继承标志 AFile := CreateFile(PChar(Fn), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_Read, @SecAtrrs, OPEN_EXISTING, FILE_ATTRIBUTE_Normal, 0); if AFile = INVALID_HANDLE_VALUE then begin Result := True; //文件被锁定 showmessage(SysErrorMessage(GetLastError)); end else Result := False; end;
4。程序的测试 在Delphi中新建一Application,在Form1的OnCreate事件中写入: if Not FileLocked(‘c:\windows\desktop\a.txt’) then Showmessage(‘Cannot Open 1’); 或 if Not LockedFile (‘c:\windows\desktop\a.txt’) then Showmessage(‘Cannot Open 2’); 再新建一批处理文件保存到桌面上,内容为: dir c:\*.*/s>c:\windows\desktop\a.txt’ 运行此批处理文件,然后运行上述Delphi程序。这时候会出现消息框“其他进程正使用该文件, 因此现在无
|
请发表评论