Можно ли разумно обойти антивирусное сканирование рабочего каталога? - PullRequest
3 голосов
/ 08 июня 2009

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

Некоторые клиенты имеют антивирусное программное обеспечение, которое сканирует один и тот же временный каталог (оно просто сканирует все). Мы пытались уговорить их отключить его - это не работает, поэтому об этом тоже не может быть и речи.

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

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

Есть ли у моего приложения разумная стратегия реагирования на ситуации, когда нужный файл заблокирован? Может быть, что-то вроде этого?

for( int i = 0; i < ReasonableNumber; i++ ) {
    try {
        performOperation(); // do useful stuff here
        break;
    } catch( ... ) {
        if( i == ReasonableNumber - 1 ) {
            throw; //not to hide errors if unlock never happens
        }
    }
    Sleep( ReasonableInterval );
 }

Это жизнеспособная стратегия? Если да, сколько раз и как часто мое приложение должно повторяться? Какие есть лучшие идеи, если таковые имеются?

Ответы [ 6 ]

4 голосов
/ 08 июня 2009

Вирусный сканер, который блокирует файлы во время их сканирования, довольно плох. Клиентам, у которых плохие вирусы, нужно заменить мозг ...; -)

Хорошо, хватит разглагольствовать. Если файл заблокирован каким-либо другим процессом, вы можете использовать стратегию «попробуйте снова», как вы предлагаете. OTOH, вам действительно нужно закрыть, а затем снова открыть эти файлы? Разве вы не можете держать их открытыми, пока ваш процесс не закончится? Один совет: добавьте задержку (спящий режим) при повторной попытке открыть файл. Около 100 мс должно быть достаточно. Если virusscanner хранит файл так долго, то это очень плохой сканер. Клиенты с плохими сканерами заслуживают сообщения об исключении, которое они увидят. Как правило, попробуйте до трех раз ... -> Открыть, при ошибке попробуйте снова, при второй ошибке попробуйте снова, при третьей ошибке просто сбой.

Не забудьте вылетать удобным для пользователя способом.

2 голосов
/ 08 июня 2009

Зависит от того, насколько велики ваши файлы, но для 10–100 с килобайт я считаю, что 5 попыток с 100 мс (0,1 секунды) будет достаточно. Если вы все еще время от времени сталкивались с ошибкой, удвойте время ожидания, но YMMV .

Если у вас есть несколько мест в коде, которые должны это сделать, могу я предложить функциональный подход:

using System;

namespace Retry
{
    class Program
    {
        static void Main(string[] args)
        {
            int i = 0;
            Utils.Retry(() =>
            {
                i = i + 1;
                if (i < 3)
                    throw new ArgumentOutOfRangeException();
            });
            Console.WriteLine(i);
            Console.Write("Press any key...");
            Console.ReadKey();
        }
    }

    class Utils
    {
        public delegate void Retryable();
        static int RETRIES = 5;
        static int WAIT = 100; /*ms*/
        static public void Retry( Retryable retryable )
        {
            int retrys = RETRIES;
            int wait = WAIT;
            Exception err;
            do
            {
                try
                {
                    err = null;
                    retryable();
                }
                catch (Exception e)
                {
                    err = e;
                    if (retrys != 1)
                    {
                        System.Threading.Thread.Sleep(wait);
                        wait *= 2;
                    }
                }
            } while( --retrys > 0 && err != null );
            if (err != null)
                throw err;
        }
    }
}
1 голос
/ 08 июня 2009

У меня был опыт работы с антивирусами, разработанными Symantec и AVG, в результате чего файлы были недоступны для открытия.

Типичная проблема, с которой мы столкнулись в 2002 году в Symantec, была с MSDev6, когда файл обновлялся в следующей последовательности:

  1. файл открыт
  2. содержимое изменено в памяти
  3. приложение должно зафиксировать изменения
  4. приложение создает новый файл tmp с новой копией файла + изменения
  5. приложение удаляет старый файл
  6. приложение копирует файл tmp в старое имя файла
  7. приложение удаляет файл tmp

Проблема возникнет между этапом 5 и этапом 6. Symantec сделает что-то, чтобы замедлить удаление, предотвращая создание файла с тем же именем (CreateFile вернул ERROR_DELETE_PENDING). MSDev6 не заметит этого, что означает, что шаг 6 провалился. Шаг 7 все же произошел. Удаление оригинала в конечном итоге закончится. Таким образом, файл больше не существует на диске!

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

Нашей резолюцией была попытка / уловка в разумном цикле, как в вопросе. Наш цикл составляет 5.

1 голос
/ 08 июня 2009

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

Ваше решение, хотя и не самое элегантное, безусловно, будет работать, пока ReasonableNumber достаточно велико - в прошлом я использовал 10 в качестве разумного числа. Я, конечно, не пошел бы выше, и вы могли бы уйти с более низким значением, таким как 5.

ценность сна? Не более 100 мс или 200 мс

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

1 голос
/ 08 июня 2009

Сложная проблема. Большинство идей, которые у меня есть, идут в направлении, которое вам не нужно (например, редизайн).

Я не знаю, сколько файлов у вас в каталоге, но если это не , то , вы можете обойти вашу проблему, если все файлы будут открыты и заблокированы во время работы вашей программы.

Таким образом, антивирусный сканер больше не сможет прерывать ваши обращения к файлам.

1 голос
/ 08 июня 2009

Не могли бы вы изменить свое приложение, чтобы не освобождать дескриптор файла? Если вы заблокируете файл самостоятельно, антивирусное приложение не сможет его отсканировать.

В противном случае, такая стратегия, как ваша, немного поможет, потому что она только уменьшает вероятность, но не решает проблему.

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