找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 9884|回复: 3

[分享] 判别文件是否被占用的方法

  [复制链接]

29

主题

134

回帖

4

精华

论坛元老

积分
5970
QQ
发表于 2010-7-17 17:11:10 | 显示全部楼层 |阅读模式
很多情况下我们需要判断一个文件是否已经被打开,查阅资料发现网上说的很杂,算了,自己研究了一下,和大家交流一下!
<1>CreateFile
BOOL IsFileOpen(LPCWSTR lpfile)
{

HANDLE fileHandle=CreateFileW(L"C:\\Users\\Administrator\\Desktop\\123456789.txt",GENERIC_READ,NULL,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(fileHandle&&fileHandle!=INVALID_HANDLE_VALUE)
{
  DWORD dw=GetLastError();
  WCHAR  szBuffer[MAX_PATH];
  swprintf(szBuffer,L"The GetLaseerror is  %d",dw);
  OutputDebugStringW(szBuffer);
CloseHandle(fileHandle);
  return TRUE;
}
else
{
  return FALSE;
}
}

msdn查阅0这个参数是必须的,代表文件以独占的方式打开,想一下,一个美女现在有了老公了,你呢 ,还想单独拥有她,结果人家很恩爱,你呢,只能是伤心了,杀了他就好了,一下容不下二虎!沙占用文件发IRp去除相应的标记即可,有空代码奉上!
<2>ZwQueryObject
很不幸运,结果测试发现有的时候打开文件第一种方法失败了!郁闷!!!思索之下,原因未找到!只能另找新的途径!结果想了一个笨办法。这种方法不支持大家用,仅参考。
BOOL IsFileOpenByHandle(LPCWSTR lpPath)
{
ULONG cbBuffer = 0x4000;
LPVOID pBuffer = NULL;
NTSTATUS s;
do
{
  pBuffer = malloc(cbBuffer);
  if(pBuffer == NULL)
   return FALSE;
  memset(pBuffer,0,cbBuffer);
  s = _ZwQuerySystemInforamtion(SystemHandleInformation,pBuffer,cbBuffer,NULL);
  if(s == STATUS_INFO_LENGTH_MISMATCH)
  {
   free(pBuffer);
   cbBuffer = cbBuffer * 2;
  }
}while(s == STATUS_INFO_LENGTH_MISMATCH);//分配好了,早晚能够了  结构体的定义大家网上搜索
PSYSTEM_HANDLE_INFORMATION_EX pInfo = (PSYSTEM_HANDLE_INFORMATION_EX)pBuffer;//PSYSTEM_HANDLE_INFORMATION_EX 自己定义 前四个节是handle 个数
for(DWORD i = 0;i<pInfo->NumberOfHandles;i++)
{
  //if(pInfo->Information.ProcessId==PID)
  {
   WCHAR szBuffer[MAX_PATH];
   BOOL zfTag=FALSE;
   zfTag=GetPathByHandle((HANDLE)pInfo->Information.Handle,szBuffer,MAX_PATH);
   if(zfTag)
   {
   
    if(_tcsnicmp(szBuffer,lpPath,_tcslen(lpPath))==0)
    {
     OutputDebugStringW(szBuffer);
     OutputDebugStringW(L"\n");
     free(pBuffer);
     return TRUE;
    }
   }
  }
  
}
free(pBuffer);
return FALSE;
}
BOOL GetPathByHandle(HANDLE hFile, LPWSTR lpBuf, DWORD nBuf) //这个方法是网上找的写的挺好
{
ULONG m, n;
WCHAR lpPath[MAX_PATH+4];
WCHAR lpDrive[MAX_PATH];
WCHAR lpDevName[MAX_PATH];

if (ZwQueryObject(hFile, 1, lpPath, MAX_PATH+4, &m) >= 0 && //如果大家不明白,参阅资料,好像ZwQueryObject,是个枚举体,1代表NameInfo,这个函数同样可以获得handle类型等等procexp.exe我感觉主要功能和这个函数密切相关,大家有兴趣可以一起探讨
  (m = GetLogicalDriveStringsW(MAX_PATH, lpDrive)) && m < MAX_PATH)  
{
  
   WCHAR *p = lpDrive;
   while (m = (ULONG)wcslen(p))
   {
    p[m-1] = L'\0';
    n = QueryDosDeviceW(p, lpDevName, MAX_PATH);
    if (n && n < MAX_PATH)
    {
     n = (ULONG)wcslen(lpDevName);
     if (!wcsnicmp(lpPath+4, lpDevName, n))
     {
      wcsncpy(lpBuf, p, nBuf);
      if (nBuf > 2) wcsncpy(lpBuf+2, lpPath+4+n, nBuf-2);
      return TRUE;
     }
    }
    p += m + 1;
   }
}
return FALSE;
}
编译通过,运行结果不过,可是没有想到和第一种方法一样,还是存在问题,不过概率对于一般的使用几乎是零

其实nt函数,功能真的相当强大,大家如果学会使用这些函数,你可以做很多坏事的,哈哈哈

评分

参与人数 1水晶币 +10 +10 收起 理由
HoviDelphic + 10 + 10 以后这样的帖子发到底层区,俺给你加亮加精 ...

查看全部评分

857

主题

2632

回帖

2

精华

管理员

此生无悔入华夏,  长居日耳曼尼亚。  

积分
36130
发表于 2010-7-17 20:39:23 | 显示全部楼层
是原创吗?支持楼主。

1214

主题

352

回帖

11

精华

管理员

菜鸟

积分
93755

贡献奖关注奖人气王精英奖乐于助人勋章

发表于 2010-7-18 10:59:06 | 显示全部楼层
感谢分享
【VB】QQ群:1422505加的请打上VB好友
【易语言】QQ群:9531809  或 177048
【FOXPRO】QQ群:6580324  或 33659603
【C/C++/VC】QQ群:3777552
【NiceBasic】QQ群:3703755

29

主题

134

回帖

4

精华

论坛元老

积分
5970
QQ
 楼主| 发表于 2010-7-18 11:13:41 | 显示全部楼层
第一种方法网上有介绍,不过第二种是俺自己想出来的,嘿嘿
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表