如何判断一个文件是否被关闭?

做项目的时候遇到了下面这个问题:如何判断一个打开的txt文件是否被关闭?
在打开一个txt文件的时候,notepad程序是自动通过文件路径的参数首先复制文件,然后马上就关闭了文件通道,这个时候打开的其实只是notepad程序而不是文件本身。文件本身的打开与关闭是一瞬间的事情。也就是说notepad程序在读取了文件以后就马上将文件关闭了。(不知道这样讲对不对,还请大家指正。)
那么我们判断一个txt文件是否被关闭其实就是判断这个notepad这个进程是否关闭。

所以一开始自己想是不是要判断进程是否被关闭。这样一来还得遍历进程判断notepad程序...而且进程名称全部都是notepad, 难道还要通过获取进程ID的方法吗?。。。。
这个方式似乎比较复杂,然后自己百度了一把看看还有没有什么更好的办法。

最后找到了下面这个方法:
http://topic.csdn.net/t/20030804/05/2104986.html
利用Windows API判断文件共享锁定状态

锁是操作系统为实现数据共享而提供的一种安全机制,它使得不同的应用程序,不同的计算机之间可以安全有效地共享和交换数据。要保证安全有效地操作共享数据,必须在相应的操作前判断锁的类型,然后才能确定数据是否可读或可写,从而为开发出健壮的程序提供切实依据。
同样,在Windows中,文件可以共享模式打开,它也涉及到锁的操作问题。根据Windows中文件共享时加锁范围的大小,锁可分为全局锁和局部锁;全局锁以锁定文件全部内容为特征,而局部锁以锁定文件的局部内容为特征,且文件的锁定区域不可重复。根据Windows中文件共享时锁的操作权限分类,锁可分为:读锁,写锁,读写锁(可读可写,全局锁)。
利用上述文件中锁的区域不可重复的特性,我们可尝试给指定文件加一全局锁。若加锁成功,说明指定文件未被其它进程锁定;否则,说明有其它进程锁定了该文件。这里,我们利用两个Windows Api文件操作函数:OpenFile和CreateFile来实现锁定状态的判断。

具体对CreateFile的第三个参数的共享模式认识还不是很深刻。。。回头再好好看看windows核心编程。。。


接着上几天的那个问题。
以前都是用WinExec或者是system函数创建的子进程,这次用CreateProcess来获得它的句柄。
CreateProcess函数。这个函数有10个参数。汗~~~~。其实我们主要用到的就是第一个参数,第二个参数,还有最后一个参数。

BOOL WINAPI CreateProcess(
__in_opt LPCTSTR lpApplicationName,
__inout_opt LPTSTR lpCommandLine,
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in BOOL bInheritHandles,
__in DWORD dwCreationFlags,
__in_opt LPVOID lpEnvironment,
__in_opt LPCTSTR lpCurrentDirectory,
__in LPSTARTUPINFO lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInformation
);

第一个参数是要打开的应用程序的路径,第二个参数是命令行参数。最后一个参数是用来返回新创建的进程的句柄。
自己仔细看了一下《windows核心编程》这本书。但是不怎么看的懂。。。因为毕竟10个参数要全部看懂的话就比较困难的。

HANDLE OpenNewFile(LPSTR NewFilePath)
{
STARTUPINFOA si = { sizeof(si) };
SECURITY_ATTRIBUTES saProcess, saThread;
PROCESS_INFORMATION piProcess;
saProcess.nLength = sizeof(saProcess);
saProcess.lpSecurityDescriptor = NULL;
saProcess.bInheritHandle = TRUE;
saThread.nLength = sizeof(saThread);
saThread.lpSecurityDescriptor = NULL;
saThread.bInheritHandle = FALSE;
CHAR Command[100];
strcpy(Command, "notepad.exe ");
strcat(Command, NewFilePath);
BOOL fRet =CreateProcessA("C:\\WINDOWS\\SYSTEM32\\NOTEPAD.EXE",
Command, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &piProcess);
if(fRet == TRUE)
return(piProcess.hProcess);
return 0;
}

这段代码的前面初始化部分是copy《windows核心编程》的。参数LPSTR NewFilePath 是文件的路径名称。
然后这个函数返回一个新创建的进程的句柄

HRes = OpenNewFile(NewFilePath);// 获得创建新进程打开notepad文件的句柄
WaitForSingleObject(HRes, INFINITE);

下面是WaitForSingleObject这个函数原型:
DWORD WINAPI WaitForSingleObject(
  __in HANDLE hHandle,
  __in DWORD dwMilliseconds
  );
这个函数很简单,第一个参数就是句柄,第二个参数是等待多少时间(以毫秒计算)。这样就达到了阻塞的效果。
如果是INFNITE,就是等到进程终止的时候才进行下面的代码,否则就一直阻塞等待。

这样一来问题就很好的解决了。

如果是直接用notepad打开某个文件,怎么知道它关闭了呢?其实思路应该还是跟上面的一样,就是首先获得这个进程的句柄,判断这个句柄是否存在,如果不存在,那么应该就是结束了。

接下来再来解决上篇博客里写的那个问题。我首先用notepad文件打开一个.txt文件。然后再用CreateFile打开这个文件,并且设置第三个参数为0,就是设置共享模式为不共享,这个时候使用CreateFile能打开文件并且获得一个句柄,这就说明这个时候notepad程序已经关闭了.txt文件。
不知道自己讲的对不对,有什么错误还恳请大家指正。


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值