2011-08-26 12 views
6

Aquí está la lógica que estoy intentando código:FileSystemWatcher se dispara antes de que se guarde el archivo. ¿Cómo se "pausa" el proceso?

El servicio supervisa un archivo .pptx en el directorio. Si el archivo ha cambiado, realice la conversión a jpg. Luego haga otras tareas, que se agregarán más tarde.

Estoy usando el archivo wather object pero eso se dispara tan pronto como abro el archivo, así que pensé en detener el proceso comprobando si el archivo está "bloqueado". Pensé que un bucle "bloqueado" haría el truco, pero no. A continuación, se muestra un prototipo de código reducido y me gustaría que, si lo mira, sugiera lo que estoy haciendo mal y/o si hay una forma mejor de escribir esto para un entorno de producción. El archivo pptx puede estar abierto durante mucho tiempo.

namespace FileWatcherDemo 
{ 
    public class Program 
    { 

    static void Main(string[] args) 
    { 
     FileSystemWatcher fsWatcher = new FileSystemWatcher(); 
     fsWatcher.Path = @"e:\\"; 

     fsWatcher.NotifyFilter = NotifyFilters.LastWrite; 

     fsWatcher.Filter = "*.pptx"; 
     fsWatcher.Changed += new FileSystemEventHandler(fsWatcher_Changed); 
     //fsWatcher.Created += new FileSystemEventHandler(fsWatcher_Changed); 
     //fsWatcher.Deleted += new FileSystemEventHandler(fsWatcher_Changed); 
     //fsWatcher.Renamed += new RenamedEventHandler(fsWatcher_Changed); 
     fsWatcher.EnableRaisingEvents = true; 
     Console.ReadKey(); 
    }   

    static void fsWatcher_Changed(object sender, FileSystemEventArgs e) 
    { 
     try 
     { 
      while(!IsFileLocked()) 
      { 
       Console.WriteLine("Changed Event Fired"); 
       Microsoft.Office.Interop.PowerPoint.Application app = new Microsoft.Office.Interop.PowerPoint.Application(); 
       Presentation pptPresentation = app.Presentations.Open(@"e:\\HowTo.pptx", MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse); 

       pptPresentation.SaveAs(@"e:\\Output", PpSaveAsFileType.ppSaveAsJPG, MsoTriState.msoFalse); 
       pptPresentation.Close(); 
      } 
     } 
     catch (Exception ex) 
     { 
      using (StreamWriter w = File.AppendText(@"e:\\ErrorLog.txt")) 
      { 
       Log(ex.Message.ToString(), w); 
       Log(ex.StackTrace.ToString(), w); 

       w.Close(); 
      } 
     } 

     Console.ReadKey(); 
    } 

    static bool IsFileLocked() 
    { 
     FileStream fs = null; 
     FileInfo file = new FileInfo(@"e:\\HowTo.pptx");    

     try 
     { 
      fs = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); 
     } 
     catch (IOException) 
     { 
      return true; 
     } 
     finally 
     { 
      if(fs != null) 
       fs.Close(); 
     } 
     return false; 
    } 

    public static void Log(string LogMessage, TextWriter w) 
    { 
     w.Write("\r\nLog Entry: "); 
     w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString()); 
     w.WriteLine(" :"); 
     w.WriteLine(" {0}", LogMessage.ToString()); 
     w.WriteLine("------------------------------------------"); 

     w.Flush(); 
    } 
} 

}

Respuesta

2

Aquí hay otra idea: Cuando el FileSystemWatcher detecta el cambio (Usted dice que se activa inmediatamente el archivo es abierto) registrar la lastModifiedTime del archivo y seguirá sonando hasta que el lastModifiedTime de los cambios en los archivos (Suponiendo que LastModifiedTime se escribe solo cuando se guarda el archivo, no sé cuándo se hace realmente) y luego realiza su proceso de conversión a JPG.

EDITAR

Adición de código que debe demostrar cómo realizar un seguimiento cuando un archivo se ha modificado:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Thread t = new Thread(()=> DoTest()); 
     t.Start(); 

     Console.WriteLine("Waiting..."); 
     Console.ReadKey(); 
    } 

    private static void DoTest() 
    { 
     FileSystemWatcher fsw = new FileSystemWatcher("C:\\"); 
     fsw.Filter = "*.txt"; 
     fsw.Changed += new FileSystemEventHandler(fsw_Changed); 
     fsw.Deleted += new FileSystemEventHandler(fsw_Deleted); 
     fsw.Renamed += new RenamedEventHandler(fsw_Renamed); 
     fsw.Created += new FileSystemEventHandler(fsw_Created); 
     fsw.EnableRaisingEvents = true; 
    } 

    static void fsw_Created(object sender, FileSystemEventArgs e) 
    { 
     FileInfo fi = new FileInfo(e.FullPath); 
     Console.WriteLine("File Created: "+e.FullPath); 
     Console.WriteLine("Creation Time: " + fi.CreationTime.ToLongTimeString()); 
     Console.WriteLine("Last Access Time: " + fi.LastAccessTime.ToLongTimeString()); 
     Console.WriteLine("Last Write Time: " + fi.LastWriteTime.ToLongTimeString()); 
     Console.WriteLine("Length: " + fi.Length); 

    } 

    static void fsw_Renamed(object sender, RenamedEventArgs e) 
    { 
     FileInfo fi = new FileInfo(e.FullPath); 
     Console.WriteLine("File Renamed: "+e.FullPath); 
     Console.WriteLine("Creation Time: " + fi.CreationTime.ToLongTimeString()); 
     Console.WriteLine("Access Time: " + fi.LastAccessTime.ToLongTimeString()); 
     Console.WriteLine("Last Write Time: " + fi.LastWriteTime.ToLongTimeString()); 
     Console.WriteLine("Length: " + fi.Length); 
    } 

    static void fsw_Deleted(object sender, FileSystemEventArgs e) 
    { 
     FileInfo fi = new FileInfo(e.FullPath); 
     Console.WriteLine("File Deleted: "+e.FullPath); 
     Console.WriteLine("Creation Time: " + fi.CreationTime.ToLongTimeString()); 
     Console.WriteLine("Last Access Time: " + fi.LastAccessTime.ToLongTimeString()); 
     Console.WriteLine("Last Write Time: " + fi.LastWriteTime.ToLongTimeString()); 

    } 

    static void fsw_Changed(object sender, FileSystemEventArgs e) 
    { 
     FileInfo fi = new FileInfo(e.FullPath); 
     Console.WriteLine("File Changed: "+e.FullPath); 
     Console.WriteLine("Creation Time: " + fi.CreationTime.ToLongTimeString()); 
     Console.WriteLine("Last Access Time: " + fi.LastAccessTime.ToLongTimeString()); 
     Console.WriteLine("Last Write Time: " + fi.LastWriteTime.ToLongTimeString()); 
     Console.WriteLine("Length: " + fi.Length); 
    } 
} 
+0

Sí, dislplays LastAccesTime de FileInfo la verdad ellos tiempo que no es el momento actual y eso es lo que quiero. Sin embargo, no hay una propiedad que rastree el cambio. ¿Cómo pruebas para eso? Gracias. – Risho

+0

@Risho No sé por qué dices que no hay ninguna propiedad que rastree el cambio. Estoy editando mi respuesta con un código de muestra. Pude monitorear un evento de cambio en un archivo y el tiempo que DID de hecho aumentó cada vez que se modificó el archivo. – Icarus

+0

porque todos los métodos fsw_ se activan tan pronto como hago clic en el archivo no cuando se guarda el archivo. Tengo que dar cuenta del hecho de que el archivo puede abrir durante horas. – Risho

1

Hay una gran cantidad de lógica de su necesidad de hacer para que el FileSystemWatcher adecuado para código de nivel de producción.

  • desea mantener los controladores de eventos muy ligero, sólo tiene que hacer cola algo que pasó y luego procesar más tarde.

  • Utilice un temporizador (System.Threading es el mejor) para procesar la cola con un retraso de 1000ms, cuando obtiene un evento, detenga/inicie el temporizador.

  • Compruebe la cola para varios eventos para el mismo archivo, p. un programa puede crear un archivo y luego eliminarlo nuevamente.

Editar: que acabo de hacer una rápida búsqueda en Google y encontró un código de artículo y de muestra que le conseguirá el 90% allí.

http://csharp-codesamples.com/2009/02/file-system-watcher-and-large-file-volumes/

http://web.archive.org/web/20120814142626/http://csharp-codesamples.com/2009/02/file-system-watcher-and-large-file-volumes/

Edición 2: Sólo volver a leer su pregunta. El consejo anterior sigue siendo válida, sin embargo algunas cosas más para que usted pueda hacer para resolver su problema:

  • Powerpoint, al igual que otras aplicaciones de Office, crea un archivo temporal oculta con un prefijo ~.

  • Compruebe las marcas de tiempo de modificación de archivo.Cuando se da cuenta por primera vez de que un archivo ha cambiado, guarde la hora de modificación y compárela con la próxima vez que se modifique el archivo.

  • Hay una propiedad de indicador del observador del sistema de archivos que deberá configurar para obtener los cambios de tiempo de modificación.

Esperanza todo esto ayuda a ...

+0

El enlace está roto. – SuperJMN

+0

@SuperJMN, gracias por informarnos. He arreglado el enlace con una copia del archivo. – Dennis

Cuestiones relacionadas