¿Hay una manera de comprobar si un archivo está en uso? [c#]


Answers

Usted puede sufrir de una condición de la raya del hilo en esto que hay ejemplos documentados de esto que es utilizado como vulnerabilidad de la seguridad. Si comprueba que el archivo está disponible, pero luego intente usarlo, podría lanzarlo en ese punto, que un usuario malintencionado podría usar para forzar y explotar en su código.

Su mejor apuesta es un try catch / finally que intenta obtener el manejador del archivo.

try
{
   using (Stream stream = new FileStream("MyFilename.txt", FileMode.Open))
   {
        // File/Stream manipulating code here
   }
} catch {
  //check here why it failed and ask user to retry if the file is in use.
}
Question

Estoy escribiendo un programa en C # que necesita tener acceso repetidamente a un archivo de imagen. La mayoría de las veces funciona, pero si mi computadora está funcionando rápido, intentará acceder al archivo antes de que se vuelva a guardar en el sistema de archivos y lance un error: "Archivo en uso por otro proceso" .

Quisiera encontrar una manera alrededor de esto, pero todo mi googling ha rendido solamente crear cheques usando el manejo de la excepción. Esto es contra mi religión, así que me preguntaba si alguien tiene una mejor manera de hacerlo?




He aquí una versión de Powerhell de la respuesta aceptada.

function IsFileLocked($filename) {

    $result = $false

    $fileinfo = [System.IO.FileInfo] (gi $filename).fullname

    try {
        $stream = $fileInfo.Open([System.IO.FileMode]"Open",[System.IO.FileAccess]"ReadWrite",[System.IO.FileShare]"None")
        $stream.Dispose()
    } catch [System.IO.IOException] {
        $result = $true
    }

    $result
}



la única manera que conozco es utilizar la API exclusiva de bloqueo de Win32 que no es demasiado rápida, pero existen ejemplos.

La mayoría de la gente, para una solución simple a esto, simplemente para probar / atrapar / dormir bucles.




static bool FileInUse(string path)
    {
        try
        {
            using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate))
            {
                fs.CanWrite
            }
            return false;
        }
        catch (IOException ex)
        {
            return true;
        }
    }

string filePath = "C:\\Documents And Settings\\yourfilename";
bool isFileInUse;

isFileInUse = FileInUse(filePath);

// Then you can do some checking
if (isFileInUse)
   Console.WriteLine("File is in use");
else
   Console.WriteLine("File is not in use");

¡Espero que esto ayude!




Simplemente utilice la excepción según lo previsto. Acepte que el archivo esté en uso e intente de nuevo, varias veces hasta que se complete su acción. Éste es también el más eficiente porque usted no pierde ningún ciclo que comprueba el estado antes de actuar.

Utilice la función siguiente, por ejemplo

TimeoutFileAction(() => { System.IO.File.etc...; return null; } );

Método reutilizable que expira después de 2 segundos

private T TimeoutFileAction<T>(Func<T> func)
{
    var started = DateTime.UtcNow;
    while ((DateTime.UtcNow - started).TotalMilliseconds < 2000)
    {
        try
        {
            return func();                    
        }
        catch (System.IO.IOException exception)
        {
            //ignore, or log somewhere if you want to
        }
    }
    return default(T);
}



Aquí hay algún código que, en la medida de lo que mejor puedo decir, hace lo mismo que la respuesta aceptada pero con menos código:

    public static bool IsFileLocked(string file)
    {
        try
        {
            using (var stream = File.OpenRead(file))
                return false;
        }
        catch (IOException)
        {
            return true;
        }        
    }

Sin embargo creo que es más robusto hacerlo de la siguiente manera:

    public static void TryToDoWithFileStream(string file, Action<FileStream> action, 
        int count, int msecTimeOut)
    {
        FileStream stream = null;
        for (var i = 0; i < count; ++i)
        {
            try
            {
                stream = File.OpenRead(file);
                break;
            }
            catch (IOException)
            {
                Thread.Sleep(msecTimeOut);
            }
        }
        action(stream);
    }



si necesita evitar el bloqueo de captura y lanzamiento, podría tener lista de cadenas, que agrega la ruta y el estado del archivo (ya sea abierto o no). por lo que puede comprobar si la ruta de acceso se accede o no desde el estado de la ruta de acceso almacenada en la lista de cadenas. Espero que lo que estoy sugiriendo es correcto, si es muy relevante mi mal.




¿Has oído hablar de una clase sigleton. si usted fuerza todas sus manipulaciones de la imagen con esta clase y hace cola todas las llamadas de la función, usted tendrá atomicity. el único problema con esto es que necesitas alojar la clase en un proceso.