Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
902 views
in Technique[技术] by (71.8m points)

c# - Delete .xlsx or .pdf after closing file

I'm trying to delete .xlsx or .pdf files after using them. When files are created I display them, but then users want automatic file deletion after closing them.

I've tried couple of things, but none of them seem to work properly. Issue:

When opened multiple files (.xlsx or .pdf) I can't terminate a single process, like just a single file. Instead what happens is that file get's deleted only when I close all same processes (Excel or PDF files). As I investigated this happens because Excel or PDF works as one instance only. However code works as expected when I have only one file opened...

This is what I have so far:

 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);
 }

I've also tried with DeleteOnClose method of FileOptions, but unfortunally that doesn't display file to user and doesn't quite delete file immediately after using them, only after my win app is closed. That isn't my desired output, but at least files are deleted, so If I could fix that I would be partially satisfied too. Here is my line for that:

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

With all that said, are there any other options I missed ? Thanks for help in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I've tried almost everything I could find (different variations of Exited_Event for Process, monitoring with FileSystemWatcher, creating files with DeleteOnClose - even API), but none of them worked as expected.

Everything ends or fails with issue I described in first place - some apps, like Microsoft Excel or Adobe Acrobat uses one instance to open a file (.pdf or .xls/.xlsx), so you can't just reference a single file as object while you have opened more files. That means you either end up with an error when trying to assign Exited_event to single file, or no error but file gets deleted only when you close all files with same type...

BUT fortunate enough I figured out one thing: WHEN you have opened more than one file in question (.pdf or .xlsx) something happens in background of OS: If you loop through processes of same type at that time, you'll get a list of particular instance that is in use.

In other words, while you have 2 Excel files opened, loop through processes is showing you only a file which is currently active for "EXCEL" process.

So, that leaded me to a completely new approach that might solve this issue. In order to have a complete solution for this you have to:

1. Create a method to check whether file is no longer in use.

2. Set a Timer with a delay of 2 seconds, to make sure process really ends. Maybe this should be incremented for different purposes...

3. Set a Timer_tick event, where you loop processes to see whether particular file is listed as active, and If user has already closed this file. As described by other users this method isn't quite accurate, but with setting delay for Timer I think there shouldn't be any problems anymore.

Here is a complete code for this (for .pdf and .xlsx - that is what I needed):

   //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;
      }

This is how I did It. It might not be a perfect solution, but that works for me on Win 10 with no errors so far.

If someone has a suggestion to fix upper code, please let me know. Otherwise I hope this will help someone in future as I noticed there were already some questions about this in past, with no proper answer.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...