2009-06-08 6 views
3

Mon application Win32 exécute de nombreuses opérations sur disque dans un dossier temporaire désigné pendant son fonctionnement, et il est hors de question de la redessiner sérieusement.Est-il possible de contourner raisonnablement un antivirus analysant le répertoire de travail?

Certains clients ont un logiciel antivirus qui analyse le même répertoire temporaire (il scanne tout simplement). Nous avons essayé de les dissuader - ça ne marche pas, donc c'est hors de question non plus.

De temps en temps (quelque chose comme une fois pour mille opérations de fichiers) mon application essaie d'effectuer une opération sur un fichier qui est à ce moment-là ouvert par l'antivirus et donc verrouillé par le système d'exploitation. Une violation de partage se produit et provoque une erreur dans mon application. Cela se produit environ une fois en trois minutes en moyenne. Le dossier temporaire peut contenir jusqu'à 100 000 fichiers dans la plupart des scénarios classiques. Je n'aime donc pas l'idée de les ouvrir à tout moment, car cela pourrait entraîner l'épuisement des ressources dans certaines conditions de contour.

Y a-t-il une stratégie raisonnable pour que mon application réagisse aux situations où un fichier requis est verrouillé? Peut-être quelque chose comme ça?

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

Est-ce une stratégie viable? Si oui, combien de fois et à quelle fréquence mon application devrait-elle réessayer? Quelles sont les meilleures idées, le cas échéant?

+1

Etes-vous sûr que l'antivirus a verrouillé le fichier? Je suis incapable d'obtenir pourquoi l'antivirus verrouillerait un fichier? Quand il charge un fichier, il devrait permettre le partage. – Canopus

+0

Peut-être l'ouvre-t-il en mode "permettre seulement les lectures en cours" et cela interdit d'écraser le fichier. Je ne peux pas dire avec certitude - les développeurs d'antivirus pourraient mieux savoir que moi. – sharptooth

Répondre

1

J'ai eu l'expérience avec le logiciel antivirus fait à la fois par Symantec et AVG qui a donné lieu dans les fichiers étant indisponible pour ouvert.

Un problème commun que nous avons connu de retour dans la période 2002 avec Symantec était avec MSDev6 lorsqu'un fichier a été mis à jour dans cette séquence:

  1. un fichier est ouvert
  2. contenu est modifié dans la mémoire
  3. application doit valider les modifications
  4. l'application crée
  5. nouveau fichier tmp avec une nouvelle copie du fichier + modifie
  6. l'application supprime
  7. ancien fichier
  8. application copie fichier tmp à l'ancien nom de fichier
  9. l'application
  10. supprime le fichier tmp

Le problème se produirait entre les étapes 5 et 6. Symantec ferait quelque chose pour ralentir le supprimer empêcher la création d'un fichier le même nom (CreateFile a renvoyé ERROR_DELETE_PENDING). MSDev6 ne remarquerait pas que l'étape 6 a échoué. L'étape 7 est toujours arrivée. La suppression de l'original finirait éventuellement. Donc le fichier n'existait plus sur le disque!

Avec AVG, nous avons rencontré des problèmes intermittents en ouvrant les fichiers qui viennent d'être modifiés.

Notre résolution était un try/catch dans une boucle raisonnable comme dans la question. Notre nombre de boucles est 5.

1

Pourriez-vous modifier votre demande de sorte que vous ne libérez pas la poignée de fichier? Si vous détenez vous-même un verrou sur le fichier, l'application antivir ne pourra pas le scanner. Sinon, une stratégie comme la vôtre aidera un peu, car elle réduit seulement la probabilité mais ne résout pas le problème.

1

Problème difficile. La plupart des idées que j'ai vont dans une direction que vous ne voulez pas (par exemple refonte). Je ne sais pas combien de fichiers vous avez dans votre répertoire, mais si ce n'est pas que vous pouvez peut-être contourner votre problème en gardant tous les fichiers ouverts et verrouillés pendant que votre programme s'exécute. De cette façon, le scanner de virus n'aura plus aucune chance d'interrompre vos accès aux fichiers.

1

S'il existe la possibilité qu'un autre processus - qu'il s'agisse du logiciel antivirus, d'un utilitaire de sauvegarde ou même de l'utilisateur lui-même - puisse ouvrir le fichier, vous devez coder cette possibilité.

Votre solution, bien qu'elle ne soit peut-être pas la plus élégante, fonctionnera certainement aussi longtemps que ReasonableNumber est suffisamment grande - dans le passé, j'ai utilisé 10 comme nombre raisonnable. Je n'irais certainement pas plus haut et vous pourriez vous en tirer avec une valeur inférieure telle que 5.

La valeur du sommeil? 100ms ou 200ms au maximum

Gardez à l'esprit que la plupart du temps, votre application recevra le fichier de la première fois.

4

Un scanneur de fichiers qui verrouille les fichiers pendant leur numérisation est très mauvais. Les clients qui ont virusscanners ce mauvais besoin d'avoir leurs cerveaux remplacés ... ;-)

D'accord, assez de ranting. Si un fichier est verrouillé par un autre processus, vous pouvez utiliser une stratégie "réessayer" comme vous le suggérez.OTOH, avez-vous vraiment besoin de fermer puis rouvrir ces fichiers? Ne pouvez-vous pas les garder ouverts jusqu'à ce que votre processus soit terminé? Un conseil: Ajoutez un délai (veille) lorsque vous essayez de rouvrir le fichier à nouveau. Environ 100 ms devraient suffire. Si le virusscanner garde le fichier ouvert aussi longtemps, c'est un vrai mauvais scanner. Les clients avec des scanners qui méritent le message d'exception qu'ils verront. En général, essayez jusqu'à trois fois ... -> Ouvrir, en cas d'échec, réessayer, en cas de deuxième échec, réessayer, en cas de troisième échec, se bloquer.

N'oubliez pas de planter de manière conviviale.

+0

Avec autant de fichiers, je me demande si c'est le système d'exploitation qui verrouille le répertoire, plutôt que le VS verrouillant des fichiers individuels. Le VS * devrait * s'ouvrir pour shared-delete, ce qui est l'ouverture la plus permissive possible. –

2

Dépend de la taille de vos fichiers, mais pour 10s à 100s de Kb, je trouve que 5 trys avec 100ms (0.1 secondes) suffisent. Si vous rencontrez toujours l'erreur de temps en temps, doublez l'attente, mais YMMV.

Si vous avez quelques endroits dans le code qui doit le faire, puis-je suggérer une approche fonctionnelle:

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

100 ms! = 0,01 sec –

+0

Euh, signifiait 0,1 pas 0,01. –

Questions connexes