Удалить .xlsx или .pdf после закрытия файла - PullRequest
1 голос
/ 23 мая 2019

Я пытаюсь удалить файлы .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);
 }

Я также пытался использовать DeleteOnClose метод FileOptions , но, к сожалению, он не отображает файл пользователю и не совсем удаляет файл сразу после использования, только после мое приложение win закрыто. Это не мой желаемый вывод, но, по крайней мере, файлы удаляются, поэтому, если бы я мог это исправить, я бы тоже был частично удовлетворен. Вот моя строка для этого:

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

С учетом всего сказанного, есть ли другие варианты, которые я пропустил? Спасибо за помощь заранее.

1 Ответ

0 голосов
/ 27 мая 2019

Я перепробовал почти все, что смог найти (различные варианты Exited_Event for Process, мониторинг с помощью FileSystemWatcher, создание файлов с помощью DeleteOnClose - даже API), но ни один из них не работал должным образом.

Все заканчивается или терпит неудачу с проблемой, которую я описал в первую очередь - некоторые приложения, такие как Microsoft Excel или Adobe Acrobat, используют один экземпляр для открытия файла (.pdf или .xls / .xlsx), поэтому вы не можетепросто ссылаться на один файл как объект, пока вы открыли больше файлов.Это означает, что вы либо сталкиваетесь с ошибкой при попытке назначить Exited_event одному файлу, либо без ошибки, но файл удаляется, только когда вы закрываете все файлы одного типа ...

НО достаточно удачно Я понял одну вещь: КОГДА вы открыли более одного рассматриваемого файла (.pdf или .xlsx), что-то происходит в фоновом режиме ОС: если вы зацикливаетесь на процессах одного типа в то время,вы получите список конкретного экземпляра, который используется.

Другими словами, пока у вас открыты 2 файла Excel, циклические процессы показывают только тот файл, который в данный момент активен для процесса «EXCEL».

Итак, это привело меня ксовершенно новый подход, который может решить эту проблему.Чтобы получить полное решение для этого, вы должны:

1. Создать метод, чтобы проверить, не используется ли файл больше.

2. Установите таймер с задержкой в ​​2 секунды, чтобы процесс действительно завершился.Может быть, это должно быть увеличено для разных целей ...

3. Установите событие Timer_tick, где вы зацикливаете процессы, чтобы увидеть, указан ли конкретный файл как активный, и если пользователь уже закрылсяэтот файл.Как описано другими пользователями, этот метод не совсем точен, но с настройкой задержки для таймера, я думаю, больше не должно быть никаких проблем.

Вот полный код для этого (для .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 без ошибок до сих пор.

Если у кого-то есть предложение исправить верхний код, пожалуйста, дайте мне знать.В противном случае, я надеюсь, что это поможет кому-то в будущем, так как я заметил, что в прошлом уже были некоторые вопросы по этому поводу, без правильного ответа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...