VC++判断目标文件是否被独占(附源码)

Posted dvlinker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC++判断目标文件是否被独占(附源码)相关的知识,希望对你有一定的参考价值。

       在IM软件中发起文件发送时,如果要发送的是某word文件,并且该word文件被office打开,则会提示文件正在被占用无法发送,如下所示:

 那文件被占用到底是如何判断出来的呢?其实很简单,调用系统API函数CreateFile,打开该文件(OPEN_EXISTING),传入FILE_SHARE_READ共享读标记位,如果文件被占用,则文件会打开失败。

1、判断文件被占用的代码

        判断文件被占用的接口函数 IsFileOccupiedByOtherProgram,实现如下:

BOOL IsFileOccupiedByOtherProgram( const CString& strFilePath )

	// 检测的办法是通过研究某软件的文件传输表现现象来确定的
	HANDLE hFile = CreateFile( strFilePath, 
		GENERIC_READ,
		FILE_SHARE_READ, // 读共享,但写不共享,如果有程序正在占用着文件写,则该函数会返回失败
		NULL, 
		OPEN_EXISTING, 
		FILE_ATTRIBUTE_NORMAL, 
		NULL );
	if ( hFile != INVALID_HANDLE_VALUE )
	
		CloseHandle( hFile ); // 文件打开成功,此处必须将句柄关闭,以释放对文件的占用
		return FALSE; // 获取到文件句柄,文件没被占用
	
	else
	
		return TRUE; // 没有获取到文件句柄,文件可能被占用
	

2、判断文件夹中是否有被占用的文件

       发起文件传输时,可能是要传一个文件夹,我们要判断文件夹中是否有文件被占用。封装的接口HasFileOccupieddByOtherProgram中一是递归调用本接口,二是调用对单个文件判断的接口IsFileOccupiedByOtherProgram。HasFileOccupieddByOtherProgram接口实现如下:

// 判断文件夹中是否有文件在被其他程序占用(其他程序可能占用着该程序并可能对程序进行写入操作,比如doc文档被WORD打开)
// 如果有被占用的文件,函数即退出
// 参数说明:strFolderDirp[in], bHasFilebOccupied[out], strbOccupiedFilePath[out]
void HasFileOccupieddByOtherProgram( const CString& strFolderDir, BOOL& bHasFilebOccupied, CString& strOccupiedFilePath )

	CString  strFindFileName = strFolderDir + _T("\\\\*.*");
	WIN32_FIND_DATA wfd;
	HANDLE hFindFile = FindFirstFile( strFindFileName, &wfd ); 
	if ( hFindFile == INVALID_HANDLE_VALUE )
	 
		return;
	

	while ( 1 )
		
		if ( bHasFileOccupied ) // 有文件被占用,则直接结束循环
		
			break;
		

		// 将文件夹中的.和..过滤掉,之前仅判断wfd.cFileName[0]是否为‘.’是有问题的,
		// 比如版本控制的代码的目录下包含掩藏的.svn文件夹,会导致文件夹大小计算有误
		//(偏小)
		if ( _tcscmp( wfd.cFileName, _T(".") ) != 0 && 
			_tcscmp( wfd.cFileName, _T("..") ) != 0 )
		// 非本级或上级目录	
			CString strFilePath = strFolderDir + _T('\\\\') + wfd.cFileName;
			if ( wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
			// 目录
				// 递归
				HasFileOccupieddByOtherProgram( strFilePath, bHasFilebOccupied , strbOccupiedFilePath );
			
			else
			// 文件
				BOOL bOccupied = IsFileOccupiedByOtherProgram( strFilePath ); // 检测当前文件是否正被其他程序占用
				if ( bOccupied )
				
					bHasFileOccupied = true;
					strbOccupiedFilePath = wfd.cFileName;
					break;
				
			
		

		if ( !FindNextFile( hFindFile, &wfd ) )
		
			break;
		
	


	FindClose( hFindFile );
	return;

3、再做一次封装,同时支持对文件和文件夹的判断

         调用该接口IsTargetFileOccupied时传入文件或文件夹的路径,然后指明当前判断对象是文件还是文件夹,如下:

// 判断被拖动的文件或文件夹中的文件是否在被其他程序占用(其他程序可能占用着该程序
// 并可能对程序进行写入操作,比如doc文档被WORD打开)
BOOL IsTargetFileOccupied( const CString& strFilePath, const EmFilePathType emFilePathType )

	if ( emFilePathType <= emInvalideType || emFilePathType > emFile )
	
		return FALSE;
	

	BOOL bFileOccupied = false;
	CString strMsg;
	if ( emFile == emFilePathType ) // 单个文件
	
		bFileOccupied = IsFileOccupiedByOtherProgram( strFilePath );
		if ( bFileOccupied )
		
		
	
	else // 文件夹
	
		CString strOccupiedFileName;
		HasFileOccupieddByOtherProgram( strFilePath, bFileOccupied , strOccupiedFileName);
		if ( bFileOccupied )
		
		
	

	return bFileOccupied ;

以上是关于VC++判断目标文件是否被独占(附源码)的主要内容,如果未能解决你的问题,请参考以下文章

VC++获取系统TCPUDP端口使用信息,并判断端口是否被占用(附源码)

VC++检测防火墙是否开启判断程序是否加入防火墙白名单(附源码)

VC++图片类型的识别(附源码)

VC++检查程序托盘图标是否掩藏到沙漏区域中(附源码)

VC++ Windows7及以上系统中管理员权限与UAC虚拟化详解(附源码)

VC++打开或关闭目标进程的声音(扬声器)(附源码)