首页 > 解决方案 > 关闭文件后删除 .xlsx 或 .pdf

问题描述

我正在尝试在使用 .xlsx 或 .pdf 文件后删除它们。创建文件时,我会显示它们,但是用户希望在关闭它们后自动删除文件。

我已经尝试了几件事,但它们似乎都不能正常工作。问题:

当打开多个文件(.xlsx 或 .pdf)时,我无法终止单个进程,就像单个文件一样。相反,只有当我关闭所有相同的进程(Excel 或 PDF 文件)时,才会删除该文件。正如我所调查的那样,发生这种情况是因为 Excel 或 PDF 仅作为一个实例工作。但是,当我只打开一个文件时,代码按预期工作......

这是我到目前为止所拥有的:

 var process= Process.Start(file_path); //file_path is global variable
 Set_event(process);

 private void Set_event(Process process)
 {
        process.EnableRaisingEvents = true;
        process.Exited += new EventHandler(Delete_File);
 }

 public void Delete_File(object sender, EventArgs e)
 {
        //Delete file on close
        File.Delete(file_path);
 }

我也尝试过FileOptions的DeleteOnClose方法,但不幸的是,它不会向用户显示文件,也不会在使用它们后立即删除文件,只有在我的 win 应用程序关闭后。这不是我想要的输出,但至少文件被删除了,所以如果我能解决这个问题,我也会部分满意。这是我的路线:

   var open_file = new FileStream(file_path,FileMode.Open, FileAccess.ReadWrite,FileShare.ReadWrite, 512, FileOptions.DeleteOnClose);

说了这么多,还有其他我错过的选择吗?提前感谢您的帮助。

标签: c#excelpdfprocess

解决方案


我已经尝试了几乎所有我能找到的东西(进程的 Exited_Event 的不同变体,使用 FileSystemWatcher 进行监视,使用 DeleteOnClose - 甚至 API 创建文件),但它们都没有按预期工作。

一切都因我首先描述的问题而结束或失败 - 某些应用程序,如 Microsoft Excel 或 Adob​​e Acrobat 使用一个实例打开文件(.pdf 或 .xls/.xlsx),因此您不能只引用单个文件作为对象,而您打开了更多文件。这意味着您要么在尝试将 Exited_event 分配给单个文件时出现错误,要么没有错误但只有在关闭所有具有相同类型的文件时才会删除文件...

但幸运的是,我发现了一件事:您打开多个有问题的文件(.pdf 或 .xlsx)时,操作系统的背景中会发生一些事情:如果您当时遍历相同类型的进程,您会得到一个正在使用的特定实例的列表。

换句话说,当您打开了 2 个 Excel 文件时,循环流程只会向您显示一个当前对“EXCEL”进程处于活动状态的文件。

因此,这使我采用了一种可能解决此问题的全新方法。为了获得完整的解决方案,您必须:

1.创建一个方法来检查文件是否不再被使用。

2.设置一个延迟2秒的定时器,以确保进程真正结束。也许这应该为不同的目的而增加......

3.设置 Timer_tick 事件,您可以在其中循环进程以查看特定文件是否被列为活动文件,以及是否用户已关闭此文件。正如其他用户所描述的,这种方法不是很准确,但是通过设置 Timer 的延迟,我认为应该不再有任何问题了。

这是一个完整的代码(对于 .pdf 和 .xlsx - 这就是我需要的):

   //as global variable
   System.Windows.Forms.Timer delete_file = new System.Windows.Forms.Timer(); 

    Process.Start(file_path); //file_path is global variable

    delete_file.Tick += new EventHandler(timer_Tick); 
    delete_file.Interval = (2000);              
    delete_file.Enabled = true;                     
    delete_file.Start();

    private void timer_Tick(object sender, EventArgs e)
    {
        Boolean file_is_opened = false;

        // Loop processes and list active files in use
        foreach (var process in Process.GetProcesses())
        {
          if (process.MainWindowTitle.Contains(Path.GetFileName(file_path)))
          {
             file_is_opened = true;
          }
        }

         //If our file is not listed under active processes we check 
         //whether user has already closed file - If so, we finally delete It
         if (file_is_opened==false)
         {
            if (!File_In_Use(new FileInfo(file_path)))
            {
                 File.Delete(file_path);
                 delete_file.Enabled = false;
                 delete_file.Stop();
                 return;
             }
          }
     }

     private bool File_In_Use(FileInfo file)
     {
         //Method to check whether file is in use

         FileStream stream = null;

         try
         {
              //If file doesn't exist
              if (!file.Exists)
              {
                     return false;
              }

              stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
         }
         catch (IOException)
         {
               //File is unavailable:
              //because someone writes to It, or It's being processed
              return true;
         }
         finally
         {
            if (stream!=null)
            {
              stream.Close();
            }
         }

             //File not locked
             return false;
      }

我就是这样做的。这可能不是一个完美的解决方案,但它在 Win 10 上对我有用,到目前为止没有错误。

如果有人有修复上层代码的建议,请告诉我。否则,我希望这对将来的某人有所帮助,因为我注意到过去已经有一些关于此的问题,但没有正确的答案。


推荐阅读