windows - Er det muligt med rimelighed at løse en antivirus scanning arbejdskataloget?

Indlæg af Hanne Mølgaard Plasc

Problem



Mit Win32-program udfører en lang række diskoperationer i en udpeget midlertidig mappe, mens den fungerer, og det er helt uden om spørgsmålet, der omdanner det alvorligt.


Nogle klienter har antivirusprogrammer, der scanner det samme midlertidige bibliotek (det scanner bare alt). Vi forsøgte at tale dem til at deaktivere det - det virker ikke, så det er heller ikke af spørgsmålet.


Hver gang en gang imellem (noget som en gang for hver tusind filoperationer) forsøger min ansøgning at udføre en operation på en fil, som på det tidspunkt er åbnet af antivirusprogrammet og derfor er låst af operativsystemet. En delingsbrud opstår og forårsager en fejl i min ansøgning. Dette sker om en gang om tre minutter i gennemsnit.


Den midlertidige mappe kan indeholde op til 100k filer i de fleste typiske scenarier, så jeg kan ikke lide ideen om at få dem til at åbne hele tiden, da dette kan medføre, at der ikke er ressourcer på nogle kantbetingelser.


Er der nogen rimelig strategi for min ansøgning at reagere på situationer, når en nødvendig fil er låst? Måske noget som dette?


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


Er dette en levedygtig strategi? Hvis ja, hvor mange gange og hvor ofte skal min ansøgning prøve igen? Hvad er bedre ideer hvis nogen?

Bedste reference


Jeg har haft erfaring med antivirusprogrammer lavet af både Symantec og AVG, hvilket resulterede i, at filer ikke var tilgængelige for åbne.


Et fælles problem, vi oplevede tilbage i 2002-tidsrammen med Symantec, var med MSDev6, da en fil blev opdateret i denne rækkefølge:



  1. en fil åbnes

  2. indholdet ændres i hukommelsen

  3. Programmet skal begå ændringer

  4. applikation opretter ny tmp-fil med ny kopi af fil + ændringer

  5. Applet sletter gammel fil

  6. ansøgningen kopierer tmp-filen til det gamle filnavn

  7. applikationen sletter tmp-filen



Problemet ville opstå mellem trin 5 og trin 6. Symantec ville gøre noget for at nedsætte sletningen, der forhindrer oprettelsen af ​​en fil med samme navn (CreateFile returneres ERROR\_DELETE\_PENDING). MSDev6 ville undlade at bemærke det - hvilket betyder, at trin 6 mislykkedes. Trin 7 er dog stadig sket. Sletningen af ​​originalen ville til sidst sluttes. Så filen eksisterede ikke længere på disk!


Med AVG har vi oplevet intermitterende problemer med at åbne filer, der netop er blevet ændret.


Vores beslutning var et forsøg/fange i en rimelig loop som i spørgsmålet. Vores sløjfetal er 5.

Andre referencer 1


En virusscanner der låser filer, mens den scanner dem, er ret dårlig. Kunder, der har virusskannere, har dette slemt behov for at få deres hjerner erstattet ... ;-)


Okay nok ranting. Hvis en fil er låst af en anden proces, kan du bruge en 'Prøv igen' -strategi som du foreslår. OTOH, skal du virkelig lukke og derefter genåbne disse filer? Kan du ikke holde dem åbne, indtil din proces er færdig?
Et tip: Tilføj en forsinkelse (søvn), når du prøver at genåbne filen igen. Ca. 100 ms skal være nok. Hvis virusscanner holder filen åben så lang tid, så er det en rigtig dårlig scanner. Kunder med scannere så slemt fortjener undtagelsesbeskeden, som de vil se.
Prøv typisk op til tre gange ... -> Åbn, ved fejl forsøge igen, ved anden fejl forsøge igen, ved tredje fejl bare crash.


Husk at kollidere på en brugervenlig måde.

Andre referencer 2


Afhængig af hvor store dine filer er, men i 10s til 100s af Kb finder jeg, at 5 trys med 100ms (0,1 sekunder) er tilstrækkelige. Hvis du stadig rammer fejlen en gang imellem, dobbelt så ventetiden, men YMMV. [4]


Hvis du har et par steder i koden, der skal gøre dette, kan jeg foreslå at tage en funktionel tilgang:


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

Andre referencer 3


Kan du ændre din ansøgning, så du ikke frigiver filhåndtaget? Hvis du holder en lås på filen selv, vil antivirprogrammet ikke kunne scanne det.


Ellers hjælper en strategi som din, lidt, fordi det kun reducerer sandsynligheden, men det løser ikke problemet.

Andre referencer 4


Tøft problem. De fleste ideer, jeg har gået i en retning, som du ikke vil have (f.eks. Redesign).


Jeg ved ikke, hvor mange filer du har i din mappe, men hvis det ikke er det , kan du muligvis løse problemet ved at holde alle filer åbne og låste, mens dit program kører.


På den måde vil virusscanneren ikke have nogen chance for at afbryde dine fil-adganger længere.

Andre referencer 5


Hvis der er mulighed for, at en anden proces - det være sig antivirusprogrammet, et backup-værktøj eller endda brugeren selv - kan åbne filen, så skal du kode for den mulighed.


Din løsning, men måske ikke den mest elegante, vil helt sikkert fungere så længe ReasonableNumber er tilstrækkeligt stor - tidligere har jeg brugt 10 som det rimelige antal. Jeg ville bestemt ikke gå højere, og du kunne få væk med en lavere værdi som 5.


Værdien af ​​søvn? Højst 100ms eller 200ms


Husk at det meste af tiden din ansøgning vil få filen første gang alligevel.