最近遇到一个问题,我在实现一个C#客户端的附件上传功能时,只能上传未被其他进程占用的文件,因此每次上传文件前需要先判断被选中文件是否被占用。尤其是PDF文件,当以AdobeReaderXI打开时,文件会处于占用状态,此时若强行上传,会触发异常。
    我上网查了下使用C#判断文件是否被占用的方法。参考了这篇博客:
    http://www.cnblogs.com/MR520/archive/2012/03/20/2408782.html
    我实现了一个函数:

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.IO;
    6. using System.Runtime.InteropServices;
    7. namespace FileStatusTest
    8. {
    9. public class FileStatusHelper
    10. {
    11. [DllImport("kernel32.dll")]
    12. public static extern IntPtr _lopen(string lpPathName, int iReadWrite);
    13. [DllImport("kernel32.dll")]
    14. public static extern bool CloseHandle(IntPtr hObject);
    15. public const int OF_READWRITE = 2;
    16. public const int OF_SHARE_DENY_NONE = 0x40;
    17. public static readonly IntPtr HFILE_ERROR = new IntPtr(-1);
    18. /// <summary>
    19. /// 查看文件是否被占用
    20. /// </summary>
    21. /// <param name="filePath"></param>
    22. /// <returns></returns>
    23. public static bool IsFileOccupied(string filePath)
    24. {
    25. IntPtr vHandle = _lopen(filePath, OF_READWRITE | OF_SHARE_DENY_NONE);
    26. CloseHandle(vHandle);
    27. return vHandle == HFILE_ERROR ? true : false;
    28. }
    29. }
    30. }

    调用方法为:

    1. if (FileStatusHelper.IsFileOccupied(@"文件路径"))
    2. {
    3. MessageBox.Show("文件已被占用");
    4. }
    5. else
    6. {
    7. MessageBox.Show("文件未被占用");
    8. }

    测试结果如下:
    1、设有一PDF文件,打开前调用函数FileStatusHelper.IsFileOccupied,显示【文件未被占用】
    2、使用AdobeReaderXI打开此PDF文件,调用函数FileStatusHelper.IsFileOccupied,显示【文件已被占用】
    3、关闭AdobeReaderXI后调用函数FileStatusHelper.IsFileOccupied,显示【文件未被占用】
    在我遇到的场景中,实现对文件是否被占用进行判别就可以了,如文件已被占用,给出相应提示并让用户自己关闭占用文件的进程即可。
    不过,在好奇心的驱使下,我还是查了下如何使用C#语言解除其他进程对文件的占用。我用搜索引擎初步找了一下,发现要想仅使用C#做到这些还真不太容易。
    后来我参考了这个stackoverflow上的问题:
    http://stackoverflow.com/questions/242882/how-can-i-unlock-a-file-that-is-locked-by-a-process-in-net
    里面给出了一个建议,使用Unlocker软件的命令行参数实现对指定文件的解锁。
    我从百度上下载的Unlocker1.9.2,下载地址如下:
    http://dlsw.baidu.com/sw-search-sp/soft/c0/12918/Unlocker1.9.2.exe
    image.png
    安装此程序后,使用下面的命令即可直接解锁指定文件:
    Unlocker.exe 要解锁的文件名 /s
    如果一定要使用C#解锁某一被占用的文件,可在Unlocker安装目录中将这四个文件提取出来:Unlocker.exe、UnlockerCOM.dll、UnlockerDriver5.sys、UnlockerHook.dll。将它们放到我们程序目录中,通过Process.Start方法调用Unlocker.exe,并附带上相关参数,就可以实现用C#代码解锁某一指定文件了。另有一点需要注意,运行Unlocker.exe时需要用到管理员权限。
    使用此方法测试结果如下:
    1、设有一PDF文件,打开前调用函数FileStatusHelper.IsFileOccupied,显示【文件未被占用】
    2、使用AdobeReaderXI打开此PDF文件,调用函数FileStatusHelper.IsFileOccupied,显示【文件已被占用】
    3、使用Unlocker解锁后,调用函数FileStatusHelper.IsFileOccupied,显示【文件未被占用】
    END
    转载于:https://www.iteye.com/blog/wx1569582009-2501076
    以下方法并不推荐,如果有其他异常也会造成被占用的错觉!

    1. public static bool FileInUse(string filename)
    2. {
    3. bool use = true;
    4. var fi = new FileInfo(filename);
    5. if (!fi.Exists) return use;
    6. FileStream fs = null;
    7. try
    8. {
    9. fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.None);
    10. use = false;
    11. }
    12. catch (Exception) { }
    13. finally
    14. {
    15. if (fs != null) fs.Close();
    16. }
    17. return use;
    18. }