2010-08-08 7 views
13

Tengo un servicio de Windows, construido usando C#, que se instala a través de un proyecto de instalación de VS2008, y estoy teniendo un par de problemas que ocurren con el proceso de desinstalación:¿Forma correcta de desinstalar un servicio de Windows?

servicio no se detiene antes de desinstalar

Cuando se ejecuta la rutina de desinstalación, se produce un error sobre los archivos en uso. Al hacer clic en continuar, se completa el instalador correctamente, pero el servicio aún aparece en la lista, por lo que no se desinstala correctamente.

(En la actualidad, tengo que recurrir a eliminarlo manualmente utilizando sc delete servicename).

Estoy tratando de detener el servicio antes de desinstalar usando el siguiente código, pero no parecen estar teniendo efecto:

protected override void OnBeforeUninstall(IDictionary savedState) 
{ 
    base.OnBeforeUninstall(savedState); 
    ServiceController serviceController = new ServiceController(MyInstaller.ServiceName); 
    serviceController.Stop(); 
} 

Cuando se llama a este código, y cómo puede dejar que el servicio antes de desinstalar?

carpeta de instalación no se elimina después de desinstalar

La aplicación también crea algunos archivos dentro de ella la carpeta de instalación cuando se ejecuta. Después de la desinstalación, la carpeta de instalación (C: \ Program Files \ MyApp) no se elimina y contiene los archivos creados por la aplicación, aunque todos los demás archivos que el instalador instaló en realidad se han eliminado correctamente.

¿Es posible que el proceso de desinstalación elimine la carpeta de instalación, incluidos todos los archivos generados dentro de esa carpeta y, de ser así, cómo?

Gracias.

Respuesta

6

Para el beneficio de todos aquellos que buscan una respuesta a estos problemas:

servicio no se detiene antes de desinstalar

todavía no ha encontrado una solución a esto.

carpeta de instalación no se elimina después de desinstalar

El método OnAfterUninstall en el instalador de proyecto debe ser anulado, y cualquier archivo creado debe ser borrado. La carpeta del instalador de la aplicación se elimina automáticamente si no contiene ningún archivo después de este paso.

protected override void OnAfterUninstall(IDictionary savedState) 
{ 
    base.OnAfterUninstall(savedState); 

    string targetDir = Context.Parameters["TargetDir"]; // Must be passed in as a parameter 

    if (targetDir.EndsWith("|")) 
     targetDir = targetDir.Substring(0, targetDir.Length-1); 

    if (!targetDir.EndsWith("\\")) 
     targetDir += "\\"; 

    if (!Directory.Exists(targetDir)) 
    { 
     Debug.WriteLine("Target dir does not exist: " + targetDir); 
     return; 
    } 

    string[] files = new[] { "File1.txt", "File2.tmp", "File3.doc" }; 
    string[] dirs = new[] { "Logs", "Temp" }; 

    foreach (string f in files) 
    { 
     string path = Path.Combine(targetDir, f); 

     if (File.Exists(path)) 
      File.Delete(path); 
    } 

    foreach (string d in dirs) 
    { 
     string path = Path.Combine(targetDir, d); 

     if (Directory.Exists(d)) 
      Directory.Delete(d, true); 
    } 

    // At this point, all generated files and directories must be deleted. 
    // The installation folder will be removed automatically. 
} 

Recuerde, la carpeta de instalación se debe pasar como parámetro:

  • Haga clic derecho sobre el proyecto de instalación, a continuación, seleccione Ver -> Acciones personalizadas
  • Las acciones personalizadas se abrirán en su ventana principal. Haga clic derecho en "Salida principal de XXX" debajo del nodo Desinstalar y seleccione "Ventana Propiedades"
  • En la ventana de propiedades, en CustomActionData, ingrese lo siguiente: /TargetDir = "[TARGETDIR] |" (observe la tubería al final, no elimine esto).

Esto pasará la carpeta de instalación como un parámetro a su rutina de desinstalación para que sepa dónde se instaló la aplicación y pueda eliminar los archivos y carpetas generados.

+1

Me gustaría una respuesta a su primer problema yo mismo. Por favor, publícalo si alguna vez lo resuelves. – PaulH

+0

@Mun Agregué [este código] (http://www.primordialcode.com/blog/post/msi-simple-delete-files-custom-action) al método 'OnAfterUninstall', pero dice que el archivo está siendo utilizado por otro proceso o acceso denegado –

1

Lo más probable es que el servicio se tome un poco de tiempo para apagarse y continúe antes de que el servicio se haya detenido por completo. Intente llamar al método WaitForStatus(ServiceControllerStatus).

Esto hará que su código espere hasta que el servicio procese el mensaje "detener" y se apaga. Una vez que el servicio se cierre realmente, ya no se mantendrá a ningún manejador de archivos.

+1

Lo he intentado sin suerte. Algunas depuraciones adicionales revelan que ninguno de los métodos de desinstalación (OnBeforeUninstall, OnAfterUninstall, Uninstall) se están llamando en realidad antes de que Windows muestre la advertencia "Archivos en uso", que sería la razón por la cual el servicio no se está deteniendo. – Mun

+0

Ah, vale. Una pregunta diferente, cuando dice "archivos creados por la aplicación", ¿quiere decir que los archivos no están presentes cuando el instalador completa la instalación, sino que se crean cuando se ejecuta la aplicación? Esos archivos pueden necesitar ser limpiados manualmente (¿después de la instalación?) ... muchos instaladores tendrán mucho cuidado con lo que "automáticamente" eliminan. –

+1

Sí, pude resolver ese problema al pasar el directorio de instalación como un parámetro personalizado y anular el método OnAfterUninstall para eliminar los archivos creados por la aplicación. Si la carpeta está vacía después de eso, el instalador la elimina automáticamente. – Mun

Cuestiones relacionadas