Я перепробовал почти все, что смог найти (различные варианты 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 без ошибок до сих пор.
Если у кого-то есть предложение исправить верхний код, пожалуйста, дайте мне знать.В противном случае, я надеюсь, что это поможет кому-то в будущем, так как я заметил, что в прошлом уже были некоторые вопросы по этому поводу, без правильного ответа.