2012-08-01 25 views
6

estoy atascado con un problema extraño (que es probablemente mi falta de conocimiento), presento el código erróneo:funciones Eliminar Elimina incluso cuando la aplicación está cerrada llamando

try 
{ 
    f.Delete(); 
    fTemp.MoveTo(f.FullName); 
    Console.WriteLine("INFO: Old file deleted new file moved in > {0}", f.FullName); 
} 
catch (IOException ex) 
{ 
    Console.WriteLine("ERROR: Output file has IO exception > {0}", f.FullName); 
    Environment.ExitCode = 1; 
} 

fy fTemp son objetos FileInfo. Entonces si ejecuto esto con un código donde f es un archivo de video que se reproduce en un reproductor multimedia, arroja la excepción. Eso funciona bien y como se esperaba. Ahora cuando cierro el reproductor multimedia, ¿se elimina el archivo? Aunque mi aplicación está cerrada desde hace mucho tiempo. Incluso cuando cierro Visual Studio, todavía elimina el archivo, cuando cierro el reproductor de medios. Como si se estuviera configurando alguna devolución de llamada en alguna parte para asegurarse de que el archivo se elimine en algún momento. Este curso en el comportamiento no deseado. Pero no puedo averiguar qué es exactamente va mal ...

resultado por ahora:

if (!IsFileLocked(f)) 
{ 
    try 
    { 
     f.Delete(); 
     fTemp.MoveTo(f.FullName); 
     Console.WriteLine("INFO: Old file deleted new file moved in > {0}", f.FullName); 
    } 
    catch (IOException ex) 
    { 
     Console.WriteLine("ERROR: Output file has IO exception > {0}", f.FullName); 
     Environment.ExitCode = 1; 

    } 

    catch (UnauthorizedAccessException ex) 
    { 
     Environment.ExitCode = 2; 
     Console.WriteLine("ERROR: Output file is locked > {0}", f.FullName); 

    } 
} 
else 
{ 
    Environment.ExitCode = 3; 
    Console.WriteLine("ERROR: Couldn't delete file was locked"); 

} 

Sé que todavía puedo hacerlo mejor entre Eliminar y MoveTo, pero voy a tomar mis cambios por ahora , codificación de escopeta .....

+5

El reproductor de medios probablemente abrió el archivo con FILE_SHARE_DELETE, lo que significa "dejar que las personas eliminen el archivo mientras lo estoy usando". El archivo está marcado para eliminar y la eliminación se completa cuando el reproductor cierra el archivo. –

+2

¿Cuál es el mensaje dado con su IOException? –

+0

Pero entonces esperaría que la excepción no se planteara. Además, lo abrí con Windows Media Player, que en mi libro está bloqueando archivos de manera infame ... ¿o no es lo mismo que la bandera que quieres decir? – JHN

Respuesta

3

Obtiene el IOException porque el archivo no se puede eliminar ni escribir de inmediato. Sin embargo, cuando llamas al Delete(), parece que se está solicitando el borrado del archivo.

Aunque el reproductor multimedia detiene la eliminación del archivo mientras está abierto, el archivo aún se marca para eliminarlo cuando se cierra, independientemente de si el programa se está ejecutando. Entonces, cuando el reproductor multimedia se cierra, el archivo se elimina.

Puede verificar si el archivo está en uso con el siguiente código, tomado de here. Haga que el Delete y el Copy estén condicionados a que no estén bloqueados, y debe estar bien.

try 
{ 
    if(!IsFileLocked(f)) 
    { 
     f.Delete(); 
     fTemp.MoveTo(f.FullName); 
     Console.WriteLine("INFO: Old file deleted new file moved in > {0}", f.FullName); 
    } 
} 

protected virtual bool IsFileLocked(FileInfo file) 
{ 
    FileStream stream = null; 

    try 
    { 
    stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); 
    } 
    catch (IOException) 
    { 
    //the file is unavailable because it is: 
    //still being written to 
    //or being processed by another thread 
    //or does not exist (has already been processed) 
    return true; 
    } 
    finally 
    { 
    if (stream != null) 
     stream.Close(); 
    } 

    //file is not locked 
    return false; 
} 
+0

¿No puedo "limpiar la bandera" o lo que sea que haya machanisme en su lugar? O mejor aún, ¿hay un control que se puede hacer si el archivo se puede eliminar en primer lugar, este comportamiento ahora es impredecible. – JHN

+0

Ver mi edición superior. –

+0

Veo, me llevó demasiado tiempo escribir mi respuesta ... :) – Hinek

1

Desde el SDK de Windows:

La función DeleteFile marca un fichero para su eliminación en una estrecha. Por lo tanto, la eliminación del archivo no se produce hasta que se cierra el último identificador del archivo. Las llamadas posteriores a CreateFile para abrir el archivo fallan con ERROR_ACCESS_DENIED.

0

Por lo que yo entiendo, desea que su programa espere hasta que el archivo se pueda eliminar y luego eliminarlo y mover el otro archivo.

Para hacer esto, podría verificar, si hay un asa abierta en el archivo, pero esto necesita un código no administrado. Otra manera sería utilizar la méthode de la respuesta de esta pregunta: Is there a way to check if a file is in use?

protected virtual bool IsFileLocked(FileInfo file) 
{ 
    FileStream stream = null; 

    try 
    { 
     stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); 
    } 
    catch (IOException) 
    { 
     //the file is unavailable because it is: 
     //still being written to 
     //or being processed by another thread 
     //or does not exist (has already been processed) 
     return true; 
    } 
    finally 
    { 
     if (stream != null) 
      stream.Close(); 
    } 

    //file is not locked 
    return false; 
} 

Antes de empezar a borrar el archivo que podría

Un bucle) hasta que el archivo se puede eliminar

while(IsFileLocked(f)) { Thread.Sleep(100); } 

o B) cancelar

if (IsFileLocked(f)) { return; } 

Si elige A o B depende en tus requerimientos

+0

Dos palabras: 'Condición de carrera' – asawyer

Cuestiones relacionadas