Pregunta

En nuestra aplicación # WinForms C, generamos archivos PDF y puesta en marcha de Adobe Reader (o lo que sea el controlador de sistema por defecto es .pdf) a través de la clase Process. Desde nuestros archivos PDF pueden ser muy grandes (aproximadamente 200 mil), manejamos el evento Exited a continuación, limpiar el archivo temporal después.

El sistema funciona como se requiere cuando se abre un archivo y luego la cerró de nuevo. Sin embargo, cuando se abre un segundo archivo (antes de cerrar Adobe Reader) el segundo proceso inmediatamente salidas (puesto lector está utilizando su poder MDI) y en nuestro manejador Exited nuestro llamado File.Delete falla porque está bloqueado por el proceso de Adobe ahora unidos . Sin embargo, en lugar del lector que obtenemos:

Se produjo un error al abrir este documento. Este archivo no se puede encontrar.

Lo inusual es que si pongo un punto de interrupción de depuración antes de la eliminación de archivos y permitir que se trate (y fallan) la eliminación, luego se comporta el sistema como se esperaba!

Estoy seguro de que el archivo existe y bastante seguro de que todos los mangos / archivo arroyos en el fichero están cerradas antes de iniciar el proceso.

Estamos lanzando con el siguiente código:

// Open the file for viewing/printing (if the default program supports it) 
var pdfProcess = new Process();
pdfProcess.StartInfo.FileName = tempFileName;
if (pdfProcess.StartInfo.Verbs.Contains("open", StringComparer.InvariantCultureIgnoreCase))
{
    var verb = pdfProcess.StartInfo.Verbs.First(v => v.Equals("open", StringComparison.InvariantCultureIgnoreCase));
    pdfProcess.StartInfo.Verb = verb;
}
pdfProcess.StartInfo.Arguments = "/N"; // Specifies a new window will be used! (But not definitely...)
pdfProcess.SynchronizingObject = this;
pdfProcess.EnableRaisingEvents = true;
pdfProcess.Exited += new EventHandler(pdfProcess_Exited);

_pdfProcessDictionary.Add(pdfProcess, tempFileName);

pdfProcess.Start();

Nota:. Estamos utilizando el _pdfProcessDictionary para almacenar referencias a los objetos de proceso para que se mantengan en su alcance de manera que evento salido de forma satisfactoria puede subirse

Nuestra limpieza / evento salido es:

void pdfProcess_Exited(object sender, EventArgs e)
{
    Debug.Assert(!InvokeRequired);
    var p = sender as Process;
    try
    {
        if (_pdfProcessDictionary.ContainsKey(p))
        {
            var tempFileName = _pdfProcessDictionary[p];
            if (File.Exists(tempFileName)) // How else can I check if I can delete it!!??
            {
                // NOTE: Will fail if the Adobe Reader application instance has been re-used!
                File.Delete(tempFileName);
                _pdfProcessDictionary.Remove(p);
            }

            CleanOtherFiles(); // This function will clean up files for any other previously exited processes in our dictionary
        }
    }
    catch (IOException ex)
    {
        // Just swallow it up, we will deal with trying to delete it at another point
    }
}

Posibles soluciones:

  • Detectar que el archivo está todavía abierto en otro proceso
  • Detectar que el segundo proceso en realidad no ha sido totalmente salido y que el archivo se abre en el primer proceso de cambio
¿Fue útil?

Solución

solo abordado este hace un par de días.

Cuando no hay ninguna instancia abrir ya, el documento se abre en una nueva instancia directamente.

Cuando hay un caso abierto, creo que genera una nueva instancia de instancia que en realidad no llega a un mango. Lo que sucede es el control vuelve a su función de inmediato, que luego va y se elimina el archivo antes de que la nueva instancia ha tenido la oportunidad de leer el archivo -. Por lo tanto, parece no estar allí

"resuelto" esto no borrar los archivos de inmediato, pero hacer el seguimiento de las trayectorias en una lista, y luego bombardear todos ellos al salir del programa (envuelven cada una de borrar en un try / catch con un bloque catch vacío caso de que el archivo ha desaparecido en el ínterin).

Otros consejos

Yo sugeriría siguiente enfoque:

  1. Crear archivos en el directorio temporal del usuario ( Path.GetTempPath ). Puede crear alguna subcarpeta debajo de ella.
  2. Intento de eliminar archivos sólo cuando última instancia de proceso se excita (es decir, que tienen que contar el número de procesos que se ha puesto en marcha, en la salida, disminuir el recuento y cuando se convierte en cero, intenta eliminar (todos los archivos) que son abrir hasta el momento)
  3. Trate de subcarpeta limpieza creado (en el directorio temp) mientras que comienza y termina la aplicación. Incluso puede intentar para temporizador periódica limpieza utilizando.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top