是否有可能合理地解决扫描工作目录的防病毒问题?

时间:2009-06-08 13:25:55

标签: windows winapi file error-handling filesystems

我的Win32应用程序在运行时在指定的临时文件夹中执行大量磁盘操作,并且严重重新设计它是不可能的。

某些客户端具有扫描同一临时目录的防病毒软件(它只扫描所有内容)。我们试图将它们说成禁用它 - 它不起作用,所以它也是不可能的。

每隔一段时间(类似于每千次文件操作一次),我的应用程序会尝试对该文件执行操作,该文件在该时间由防病毒程序打开,因此被操作系统锁定。发生共享冲突并导致我的应用程序出错。这种情况平均每三分钟发生一次。

在大多数典型情况下,临时文件夹最多可包含100k个文件,因此我不喜欢随时打开它们的想法,因为这可能会导致某些边缘条件下的资源耗尽。

我的应用程序是否有一些合理的策略来应对所需文件被锁定的情况?也许是这样的?

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 个答案:

答案 0 :(得分:4)

在扫描文件时锁定文件的病毒扫描程序非常糟糕。那些病毒严重的客户需要更换他们的大脑...; - )

好的,足够的咆哮。如果某个文件被某个其他进程锁定,那么您可以像您建议的那样使用“重试”策略。 OTOH,你真的需要关闭然后重新打开这些文件吗?在您的流程完成之前,您不能让它们保持打开状态吗? 一个提示:当您尝试再次重新打开文件时添加延迟(休眠)。大约100毫秒就足够了。如果virusscanner保持文件打开那么久,那么它就是一个真正糟糕的扫描仪。扫描仪坏的客户端应该看到他们会看到的异常消息。 通常情况下,最多尝试三次...... - &gt;打开,失败时再试一次,第二次失败再试一次,第三次失败只是崩溃。

请记住以用户友好的方式崩溃。

答案 1 :(得分:2)

取决于你的文件有多大,但对于10s到100s的Kb,我发现5次100ms(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;
        }
    }
}

答案 2 :(得分:1)

您是否可以更改应用程序,以免释放文件句柄?如果您自己锁定文件,则antivir应用程序将无法扫描它。

否则像你这样的策略会有所帮助,因为它只会降低概率但却无法解决问题。

答案 3 :(得分:1)

难题。大多数想法都指向了你不想要的方向(例如重新设计)。

我不知道您的目录中有多少个文件,但是如果它不是那么你可以通过在程序运行时保持所有文件打开并锁定来解决您的问题

这样病毒扫描程序将无法再中断文件访问。

答案 4 :(得分:1)

如果有可能某个其他进程 - 无论是防病毒软件,备份实用程序,还是用户自己 - 都可以打开该文件,那么您必须编写这种可能性的代码。

你的解决方案虽然可能不是最优雅的,但只要ReasonableNumber足够大,肯定会起作用 - 过去我使用10作为合理的数字。我当然不会更高,你可以使用较低的值,例如5。

睡眠的价值?最多100毫秒或200毫秒

请记住,大多数情况下,您的应用程序无论如何都会首次获取该文件。

答案 5 :(得分:1)

我有使用赛门铁克和AVG制作的防病毒软件的经验,导致文件无法打开。

我们在赛门铁克2002年的时间框架内遇到的一个常见问题是在文件按此顺序更新时使用MSDev6:

  1. 打开文件
  2. 内容在内存中被修改
  3. 应用程序需要提交更改
  4. 应用程序使用文件+更改的新副本
  5. 创建新的tmp文件
  6. 应用程序删除旧文件
  7. 应用程序将tmp文件复制到旧文件名
  8. 应用程序删除tmp文件
  9. 在步骤5和步骤6之间会出现问题.Symantec会做一些事情来减慢删除速度,从而阻止创建具有相同名称的文件(CreateFile返回ERROR_DELETE_PENDING)。 MSDev6将没有注意到 - 意味着第6步失败。第7步仍然发生了。删除原件最终将完成。所以该文件不再存在于磁盘上!

    使用AVG,我们遇到了能够打开刚修改过的文件的间歇性问题。

    我们的解决方案是在问题中合理循环中的try / catch。我们的循环计数是5。