winforms - Корректное удаление файлов C#


3

Написал такой метод для удаления файлов

public static void deleteFile(params string[] fileName)
{
    foreach (string f in fileName)
    {
        if (File.Exists(Properties.Settings.Default.diskString + f)) File.Delete(Properties.Settings.Default.diskString + f);
    }
}

Вызываю так:

HelpClass.deleteFile("poster.jpg", "1.jpg", "2.jpg", "3.jpg", "4.jpg", downloadFileName);

Вот эти файлы, перечисленные в аргументах метода, предварительно вставляются в поля сайта через webbrowser. Соответственно, при запуске метода файлы якобы удаляются, но на самом деле остаются до полного закрытия программы. Прикрепил скрин, как они на диске выглядят после этого. Если попытаться их открыть, то пишет, что отсутствует разрешение на доступ к расположению файла. Если же в webbrowser их не вставлять, то все хорошо удаляется. Пытался очищать память при закрытии второй формы (событие FormClosed), на которой находится webbrowser, двумя способами:

this.Dispose();

и

GG.Collect();

результата нет. Один раз сработал второй способ, но больше почему-то не работает))

Файлы в поля на сайте вставляются следующим образом:

Populate().ContinueWith((_) =>
        {

        }, TaskScheduler.FromCurrentSynchronizationContext());

async Task PopulateInputFile_poster(HtmlElement file_poster)
{
    file_poster.Focus();
    dialog show up
    var sendKeyTask = Task.Delay(500).ContinueWith((_) =>
        {
            SendKeys.Send(Properties.Settings.Default.diskString + "" + "poster.jpg" + "{ENTER}");
        }, TaskScheduler.FromCurrentSynchronizationContext());

    file_poster.InvokeMember("Click"); 

    await sendKeyTask;

    await Task.Delay(500);
}

async Task Populate()
{
    var elements = webBrowser1.Document.GetElementsByTagName("input");


    //постер
    foreach (HtmlElement file_poster in elements)
    {
        if (file_poster.GetAttribute("name") == "screen")
        {
            file_poster.Focus();
            await PopulateInputFile_poster(file_poster);
        }
    }
}

Подскажите, что не так? введите сюда описание изображения

Источник
  •  116
  •  1
  • 24 янв 2018 2018-01-24 04:08:28
Тогда странная ситуация. А метод deleteFile() вызывается когда? Сразу после того как как запустил аплоад? Или через некоторое время? Может он не успевает залить как ты пытаешся удалить — 20 янв 20182018-01-20 19:49:17.000000
@Andrew в методах, где я скачиваю файлы, Везде прописан Dispose. Проверил. Да и обернуты все скачивания в using, т.е. они автоматически должны закрыться. Значит остается использование этих файлов при вставке в input в webbrowser. Код этого я привел в своем посте. Можете глянуть, надо ли там что-то закрывать? — 20 янв 20182018-01-20 18:43:41.000000
если ты открываешь поток для чтения файла - нужно его закрывать. Если ты открываешь файл с некими правами - нужно освободить это открытие. Где конкретно ты это сделал я не подскажу. Но советую почитать, например, про .Dispose() метод в IDisposable обьектов. 99% что ты где-то файлы открывал и банально не закрыл. — 20 янв 20182018-01-20 17:12:04.000000
@UladzimirPalekh а можете объяснить, как это сделать с помощью данной программы? Я только понял, что появились новые потоки после запуска второй формы. И они не исчезли после ее закрытия... — 20 янв 20182018-01-20 16:33:12.000000
Разбирайтесь, кто держит дескриптор файлов после загрузки. Для этого можете воспользоваться Process Explorerом technet.microsoft.com/ru-ru/sysinternals/bb896653 20 янв 20182018-01-20 15:49:12.000000

1 ответ

5

Нашел похожую проблему вот тут

Там говорится, что если перейти на произвольный адрес, например, http://localhost/ , то ресурсы освобождаются и могут быть удалены.

В этом вопросе так же сталкиваются с этой проблемой и предлагают такое же решение:

webBrowser.Navigate("about:blank");
while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
    Application.DoEvents();

File.Delete(fileName);

Если это не поможет, то можно подойти радикально, используя AppDomain:

  1. Создаете класс наследник от MarshalByRefObject
  2. Оборачиваете этот класс вокруг webbrowser
  3. Создаете новый домен
  4. В этом домене создаете объект вашего класса
  5. Взаимодействуете с браузером через него
  6. Когда хотите удалить файлы, выгружаете домен целиком

Как вариант, еще можно попробовать стороннюю библиотеку CefSharp . Она является альтернативой webbrowser на хромиуме.

  • 30 янв 2018 2018-01-30 20:19:47
А вы используется веббраузер для тестирования сайта? — 30 янв 20182018-01-30 11:02:39.000000
а разве у webClient есть графический интерфейс? Мне необходимо наглядно видеть как заполнились те или иные поля на сайте, чтобы, в случае чего, отредактировать их. А можно поподробнее про отдельный домен? — 30 янв 20182018-01-30 11:02:39.000000
@АндрейФедоров Ну есть радикальный подход, вы можете работать в webbrowser в отдельном домене, а потом его выгружать перед удалением файлов. — 30 янв 20182018-01-30 11:02:39.000000
@АндрейФедоров, а зачем вы используете webbrowser? Чем легковесный WebClient не устраивает? — 30 янв 20182018-01-30 11:02:39.000000
Кинул на вторую форму кнопку, на которую прописал Ваш код, но результат тот же... — 30 янв 20182018-01-30 11:02:39.000000