.NET中检测文件是否被其他进程占用
更新记录
本文迁移自Panda666原博客,原发布时间:2021年7月2日。
一、检测文件是否被进程占用的几种方式
在.NET中主要有以下方式进行检测文件是否被进程占用的几种方式:
- 通过直接打开文件等操作,根据是否弹出异常来判断是否被其他进程占用。
- 使用互操作去检测文件是否被其他进程占用。
二、使用异常来测试是否被其他进程占用
直接打开文件进行读,因为文件不完整,所以会抛出异常。通过goto实现一直监听文件是否复制完成。因为异常的性能相比正常代码性能非常低,并且使用异常来实现代码逻辑也非常不合适,所以建议使用另一种方法进行实现同样的功能。
代码实例:
using System;
using System.IO;
using System.Linq;
using System.Threading;
namespace PandaTestClass
{
class Program
{
static void Main(string[] args)
{
//新建文件监听器
FileSystemWatcher watcher = new FileSystemWatcher();
//====配置文件监听器=====
//监听的目录
string monitoredPath = @"E:/";
//监听的文件类型
string monitoredFileType = "*.txt|*.cs";
//监听的修改的具体操作类型
NotifyFilters notifyFilters = NotifyFilters.FileName
| NotifyFilters.Size
| NotifyFilters.LastWrite;
//设置参数
watcher.Path = monitoredPath;
monitoredFileType.Split("|")
.ToList()
.ForEach(elem => watcher.Filters.Add(elem));
watcher.NotifyFilter = notifyFilters;
//====配置文件监听器=====
//====绑定事件处理函数====
//绑定文件修改事件处理函数
watcher.Changed += (object sender, FileSystemEventArgs args) => {
Console.WriteLine("文件修改啦");
Console.WriteLine($"被修改的文件是{args.Name}");
Console.WriteLine($"被修改的文件文件路径是{args.FullPath}");
Console.WriteLine($"修改的类型{args.ChangeType.ToString()}");
//====检测创建后是否可用(比如:是否复制完成)====
//先检测文件是否存在
FileInfo fileInfo = new(args.FullPath);
if (!fileInfo.Exists)
{
return;
}
//检测文件是否复制完成
NotComplate: try
{
File.OpenRead(fileInfo.FullName);
}
catch(Exception e)
{
Console.WriteLine("文件还未复制完成");
Thread.Sleep(TimeSpan.FromSeconds(3));
goto NotComplate;
}
//可以对文件进行操作
Console.WriteLine("可以对文件进行操作了");
//====检测创建后是否可用(比如:是否复制完成)====
//对文件具体操作的代码
};
//====绑定事件处理函数====
//开启监听
watcher.EnableRaisingEvents = true;
//等待用户关闭监听
while (true)
{
Console.WriteLine("如需关闭监听,请按Y:");
if ((Console.ReadKey()).Key == ConsoleKey.Y)
{
//释放监听器
watcher.Dispose();
return;
}
}
}
}
}
三、通过互操作检测文件是否被其他进程占用
首先,需要在代码中引入互操作函数和常量。
打开文件用于测试文件是否可用。
[DllImport("kernel32.dll")]
public static extern IntPtr _lopen(string lpPathName, int iReadWrite);
关闭句柄,用于关闭已打开的文件句柄。
[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr hObject);
文件打开的模式-读写
public const int OF_READWRITE = 2;
文件打开的模式-共享读写
public const int OF_SHARE_DENY_NONE = 0x40;
文件打开错误标志位,用于判断文件打开后的状态判断
public static readonly IntPtr HFILE_ERROR = new IntPtr(-1);
在每次进行文件操作前,对文件进行测试是否可以访问
//检测文件是被其他进程占用
IntPtr vHandle = _lopen(args.FullPath, OF_READWRITE | OF_SHARE_DENY_NONE);
if (vHandle == HFILE_ERROR)
{
Console.WriteLine("文件被其他进程占用,不可以操作");
return;
}
//释放句柄
CloseHandle(vHandle);
//文件可以操作了
代码实例:监听文件的操作,如果文件复制完成了再进行操作
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace PandaTestClass
{
class Program
{
/// <summary>
/// 打开文件,用于测试文件是否可用
/// </summary>
/// <param name="lpPathName"></param>
/// <param name="iReadWrite"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
public static extern IntPtr _lopen(string lpPathName, int iReadWrite);
/// <summary>
/// 关闭句柄
/// </summary>
/// <param name="hObject"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr hObject);
/// <summary>
/// 文件打开的模式,读写权限
/// </summary>
public const int OF_READWRITE = 2;
/// <summary>
/// 文件打开的模式,进程间共享读写
/// </summary>
public const int OF_SHARE_DENY_NONE = 0x40;
/// <summary>
/// 文件打开错误标志位
/// </summary>
public static readonly IntPtr HFILE_ERROR = new IntPtr(-1);
static void Main(string[] args)
{
//新建文件监听器
FileSystemWatcher watcher = new FileSystemWatcher();
//====配置文件监听器=====
//监听的目录
string monitoredPath = @"E:/";
//监听的文件类型
string monitoredFileType = "*.txt|*.cs";
//监听的修改的具体操作类型
NotifyFilters notifyFilters = NotifyFilters.FileName
| NotifyFilters.Size
| NotifyFilters.LastWrite;
//设置参数
watcher.Path = monitoredPath;
monitoredFileType.Split("|")
.ToList()
.ForEach(elem => watcher.Filters.Add(elem));
watcher.NotifyFilter = notifyFilters;
//====配置文件监听器=====
//====绑定事件处理函数====
//绑定文件修改事件处理函数
watcher.Changed += (object sender, FileSystemEventArgs args) => {
Console.WriteLine("文件修改啦");
Console.WriteLine($"被修改的文件是{args.Name}");
Console.WriteLine($"被修改的文件文件路径是{args.FullPath}");
Console.WriteLine($"修改的类型{args.ChangeType.ToString()}");
//====检测创建后是否可用(比如:是否复制完成)====
//先检测文件是否存在
FileInfo fileInfo = new(args.FullPath);
if (!fileInfo.Exists)
{
return;
}
//检测文件是否复制完成
IntPtr vHandle = _lopen(args.FullPath, OF_READWRITE | OF_SHARE_DENY_NONE);
if (vHandle == HFILE_ERROR)
{
Console.WriteLine("文件还未复制完成");
return;
}
//释放句柄
CloseHandle(vHandle);
//可以对文件进行操作
Console.WriteLine("可以对文件进行操作了");
//====检测创建后是否可用(比如:是否复制完成)====
//对文件具体操作的代码
};
//====绑定事件处理函数====
//开启监听
watcher.EnableRaisingEvents = true;
//等待用户关闭监听
while (true)
{
Console.WriteLine("如需关闭监听,请按Y:");
if ((Console.ReadKey()).Key == ConsoleKey.Y)
{
//释放监听器
watcher.Dispose();
return;
}
}
}
}
}
.NET中检测文件是否被其他进程占用的更多相关文章
- 使用c#检测文件正在被那个进程占用 判断文件是否被占用的两种方法
C# 判断文件是否被占用的三种方法 using System.IO; using System.Runtime.InteropServices; [DllImport("kernel32.d ...
- 使用c#检测文件正在被那个进程占用
要检测文件被那个进程占用,需要使用微软提供的工具Handle.exe,这里有微软提供的下载 我们可以在c#中调用Handle.exe 来检测到底哪个进程占用了文件 string fileName = ...
- 在.NetCore中使用Myrmec检测文件真实格式
Myrmec 是什么? Myrmec 是一个用于检测文件格式的库,Myrmec不同于其它库或者手写检测代码,Myrmec不依赖文件扩展名(在实际使用中,你的用户很可能使用虚假的扩展名欺骗你的应用程序) ...
- sqlserver检测死锁;杀死锁和进程;查看锁信息
http://blog.sina.com.cn/s/blog_9dcdd2020101nf4v.html sqlserver检测死锁;杀死锁和进程;查看锁信息 ( ::)转载▼ 标签: sql 检测死 ...
- 如何在 Linux 中查看进程占用的端口号【转】
对于 Linux 系统管理员来说,清楚某个服务是否正确地绑定或监听某个端口,是至关重要的.如果你需要处理端口相关的问题,这篇文章可能会对你有用. 端口是 Linux 系统上特定进程之间逻辑连接的标识, ...
- C++之检测文件结尾
当使用文件作为输入流时,为了确保适时的结束文件读取操作,程序要靠检查文件尾来判断该何时停止读取.常用的检查文件尾方法有两种: 两种方式均已将 fin 与文件关联,即 均已声明 fin 输入流,并已调用 ...
- linux中Makefile文件相关内容
第一章.概述什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional(专业)的程序员,m ...
- 关于Python中的文件操作(转)
总是记不住API.昨晚写的时候用到了这些,但是没记住,于是就索性整理一下吧: python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Pyth ...
- 从客户端中检测到有潜在危险的 request.form值[解决方法]
当页面编辑或运行提交时,出现“从客户端中检测到有潜在危险的request.form值”问题,该怎么办呢?如下图所示: 下面博主汇总出现这种错误的几种解决方法:问题原因:由于在asp.net中,Requ ...
随机推荐
- 制作java的docker镜像
Dockerfile如下: FROM ubuntu:16.04 MAINTAINER tanyiqu ADD jdk-8u231-linux-x64.tar.gz /usr/local/ ENV JA ...
- mysql4与mysql5的区别_MySQL 4.1/5.0/5.1/5.5/5.6各版本的主要区别
MySQL 4.1/5.0/5.1/5.5/5.6各版本的主要区别 一.5.0 增加了Stored procedures.Views.Cursors.Triggers.XA transactions的 ...
- Typora中Markdown学习
Typora中Markdown学习 标题 可以自己设置标题级数,且各标题之间可在大纲处看到鲜明的层级关系,非常方便清楚. "#"--一级标题 "##"--二级标 ...
- 邮件任务-springboot
邮件任务-springboot springboot可以很容易实现邮件的发送 具体实现步骤: 导入jar包 <dependency> <groupId>org.springfr ...
- EMC信号完整性落地实测1---走出玄学
EMC信号完整性落地实测1---走出玄学 无论我们从51单片机,STM32电路,运放,传感器,ADC采集还是可控硅晶闸管等等电源电路跨入到电子工程师的行业,我们通常会长时间处于低频的电子电路设计调试阶 ...
- Hoo Smart Chain 万物生长计划火热报名中,可视化公链迸发勃勃生机
在DeFi越来越趋向同质化和静态化时,Hoo Smart Chain决定充当破局者,宣布决定All In元宇宙,并于2022年3月份开启面向全球去中心化开发者的奖励计划--「万物生长计划」 目前Ter ...
- CVPR 2022数据集汇总|包含目标检测、多模态等方向
前言 本文收集汇总了目前CVPR 2022已放出的一些数据集资源. 转载自极市平台 欢迎关注公众号CV技术指南,专注于计算机视觉的技术总结.最新技术跟踪.经典论文解读.CV招聘信息. M5Produc ...
- 比 Navicat 还要好用、功能更强大的工具!
DBeaver 是一个基于 Java 开发,免费开源的通用数据库管理和开发工具,使用非常友好的 ASL 协议.可以通过官方网站或者 Github 进行下载. 由于 DBeaver 基于 Java 开发 ...
- IOC简介 -Bean的作用域 创建对象
创建对象 创建对象时默认使用无参构造器,无论对象在容器中后续是否被使用, 都会先实例化对象 . (婚介网站,里面人都是先存在的,到时直接牵手就行) 也可以使用以下方法,使用有参构造器来创建对象 根据参 ...
- Redis实现并发阻塞锁方案
由于用户同时访问线上的下订单接口,导致在扣减库存时出现了异常,这是一个很典型的并发问题,本篇文章为解决并发问题而生,采用的技术为Redis锁机制+多线程的阻塞唤醒方法. 在实现Redis锁机制之前,我 ...