利用Windows API判斷檔案共享鎖定狀態

2021-04-14 02:01:39 字數 4814 閱讀 8020

一、概述

鎖是作業系統為實現資料共享而提供的一種安全機制,它使得不同的應用程式,不同的計算機之間可以安全有效地共享和交換資料。要保證安全有效地操作共享資料,必須在相應的操作前判斷鎖的型別,然後才能確定資料是否可讀或可寫,從而為開發出健壯的程式提供切實依據。

同樣,在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:期望訪問模式

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。程式的測試

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程式。這時候會出現訊息框「其他程序正使用該檔案, 因此現在無法訪問。」。當批處理命令執行完畢後,再執行此程式則不會出現此資訊。此時,再雙擊a.txt文件,記事本程式將無法開啟該文件,說明加鎖成功。

三、結束語

以上用兩種方法實現了如何判斷乙個檔案是否正被其它程序鎖定。其中,方法一實現較為簡單,但相容性不好;而方法二為windows推薦的方法,且功能強大。

利用以上實現方法,較好地解決了windows下檔案鎖定狀態判斷的問題。為避免發生共享衝突和提高檔案操作程式的健壯性提供了很好的參考依據。

以上程式在windows98,delphi6下測試通過。 

利用windows api實現程序通訊(命名管道)

服務端 1.使用api函式createnamedpipe建立與命名管道的連線。2.使用api函式connectnamedpipe等待客戶端的連線。可用這個函式將乙個管道換成同另乙個客戶連線,也就是可以重複呼叫該函式,但必須用disconnectnamedpipe函式斷開之前程序的連線 3.使用api...

利用Windows API實現螢幕取色器

一 效果圖 為了實現這個取色器,在網上查了很多關於取色器的資料,起先是通過winform怎麼製作,後來發現大多數資料都呼叫了windows api,但自己以前從來沒有用過這方面的,又從網上下了windows api 來看,經過多次實踐終於做出了現在這個效果,先感謝下網上那些提供資料的朋友。效果,如下...

c 通過Windows API 判斷網路是否連線

win32 api函式的做法 要用的函式 internetgetconnectedstate 函式原形 bool internetgetconnectedstate lpdword lpdwflags,dword dwreserved 引數lpdwflags返回當前網路狀態,引數dwreserved...