zoukankan      html  css  js  c++  java
  • Delphi Windows API判断文件共享锁定状态(OpenFile和CreateFile两种方法)

    一、概述 
    锁是操作系统为实现数据共享而提供的一种安全机制,它使得不同的应用程序,不同的计算机之间可以安全有效地共享和交换数据。要保证安全有效地操作共享数据,必须在相应的操作前判断锁的类型,然后才能确定数据是否可读或可写,从而为开发出健壮的程序提供切实依据。   
    同样,在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:windowsdesktopa.txt’)   then   Showmessage(‘Cannot   Open   1’);   
    或   
    if   Not   LockedFile   (‘c:windowsdesktopa.txt’)   then   Showmessage(‘Cannot   Open   2’);   
    再新建一批处理文件保存到桌面上,内容为:   
    dir   c:*.*/s> c:windowsdesktopa.txt’   
    运行此批处理文件,然后运行上述Delphi程序。这时候会出现消息框“其他进程正使用该文件,   因此现在无法访问。”。当批处理命令运行完毕后,再运行此程序则不会出现此信息。此时,再双击a.txt文档,记事本程序将无法打开该文档,说明加锁成功。   

    三、结束语   
    以上用两种方法实现了如何判断一个文件是否正被其它进程锁定。其中,方法一实现较为简单,但兼容性不好;而方法二为Windows推荐的方法,且功能强大。   
    利用以上实现方法,较好地解决了Windows下文件锁定状态判断的问题。为避免发生共享冲突和提高文件操作程序的健壮性提供了很好的参考依据。   

    http://blog.csdn.net/yanjiaye520/article/details/7880967

  • 相关阅读:
    java.net.SocketException: Unrecognized Windows Sockets error: 0: JVM_Bind
    Spring读书笔记Spring核心机制:依赖注入
    Java邮件开发JavaMail(二)
    Spring 读书笔记Spring容器(一)
    Spring读书笔记部署我的第一个Spring项目 .
    解决org.hibernate.QueryException illegal attempt to dereference collection 异常错误
    我的求职历程求职总结
    Java邮件开发JavaMail(三)
    silverlight在firefox上经常崩溃
    silverlight的开发暂时是痛苦的
  • 原文地址:https://www.cnblogs.com/findumars/p/4987297.html
Copyright © 2011-2022 走看看