El servicio de Windows en la computadora local se inició y luego detuvo el error

104

Por lo general, obtengo este error: (El servicio "nombre del servicio" en la computadora local se inició y luego se detuvo. Algunos servicios se detienen automáticamente si no están siendo utilizados por otros servicios o programas) cuando hay algún problema con mi código, como no existente rutas de acceso, etc. El servicio de Windows no se iniciará.

Tengo un servicio de Windows que hace copias de seguridad de carpetas / archivos, en una ubicación si alcanzó el límite de tamaño. Todos los detalles son proporcionados por una configuración XML que el servicio de Windows lee al inicio. Tengo formularios de Windows separados que tienen un botón que hace exactamente lo que hace el inicio de mi servicio de Windows. Utilizo mis formularios de Windows para depurar el código antes de ponerlo en mi servicio de Windows.

Cuando comienzo mis formularios de Windows. Hace lo que se supone que debe hacer. Cuando puse mi código en el método OnStart () del servicio de Windows, apareció el error.

Aquí está mi código:

protected override void OnStart(string[] args)
{

    private static string backupConfig = @"D:\LogBackupConfig\backupconfig.xml";
    private static string serviceStat = @"D:\LogBackupConfig\Status.txt";
    private static string fileFolderStat = @"D:\LogBackupConfig\FileFolderStat.txt";

    protected override void OnStart(string[] args)
    {
        if (File.Exists(backupConfig))
        {
            FileSystemWatcher watcher = new FileSystemWatcher();
            XmlTextReader reader = new XmlTextReader(backupConfig);

            XmlNodeType type;
            List<string> listFile = new List<string>();
            string fileWatch = "";

            //this loop is for reading XML elements and assigning to variables
            while (reader.Read())
            {
                type = reader.NodeType;
                if (type == XmlNodeType.Element)
                {
                    if (reader.Name == "File")
                    {
                        reader.Read();
                        fileWatch = reader.Value;
                    }
                    else if (reader.Name == "Folder")
                    {
                        reader.Read();
                        fileWatch = reader.Value;
                    }
                }
            }
            reader.Close();

            watcher.Path = fileWatch;
            watcher.Filter = "*.*";

            //this loop reads whether the service will watch a file/folder
            XmlTextReader reader1 = new XmlTextReader(backupConfig);
            while (reader1.Read())
            {
                type = reader1.NodeType;
                if (type == XmlNodeType.Element)
                {
                    if (reader1.Name == "File")
                    {
                        watcher.IncludeSubdirectories = false;
                        watcher.Changed += new FileSystemEventHandler(OnChangedFile);
                    }
                    else if (reader1.Name == "Folder")
                    {
                        watcher.IncludeSubdirectories = true;
                        watcher.Changed += new FileSystemEventHandler(OnChangedFolder);
                    }
                }
            }
            reader1.Close();

            watcher.EnableRaisingEvents = true;

        }
        else
        {
            StreamWriter sw = new StreamWriter(serviceStat, true);
            sw.WriteLine("File not found. Please start the Log Backup UI first.");
            sw.Close();
        }
    }

No sé qué hace que el servicio de Windows no se inicie, el simulador de formularios de Windows funcionó bien. ¿Cuál parece ser el problema?

ACTUALIZACIÓN: Después de muchas pruebas, he notado que al usar solo un directorio de carpetas (sin archivo), el servicio de Windows no funciona. Cuando reemplacé la variable fileWatch con un archivo específico (incluido su directorio), se inició el servicio de Windows. Cuando lo cambié de nuevo a una ubicación de carpeta, no funcionó. Lo que creo es que las ubicaciones de las carpetas no funcionan en un observador de archivos.

Cuando intenté crear un nuevo servicio de Windows que observe la ubicación de una carpeta, funcionó. Sin embargo, cuando probé la misma ubicación en mi servicio de Windows original, ¡no funcionó! ¡Estaba loco! Parece que tengo que crear un nuevo servicio de Windows y compilar el instalador cada vez que coloco un nuevo código / función. De esta manera puedo hacer un seguimiento de dónde obtengo un error.

Blackator
fuente

Respuestas:

202

Si el servicio se inicia y se detiene así, significa que su código está lanzando una excepción no controlada. Esto es bastante difícil de depurar, pero hay algunas opciones.

  1. Consulte el Visor de eventos de Windows . Normalmente, puede acceder a esto yendo al administrador de la computadora / servidor, luego haciendo clic en Visor de eventos -> Registros de Windows -> Aplicación . Puede ver qué generó la excepción aquí, lo que puede ayudar, pero no obtiene el seguimiento de la pila.
  2. Extraiga la lógica de su programa en un proyecto de clase de biblioteca. Ahora cree dos versiones diferentes del programa: una aplicación de consola (para depurar) y el servicio de Windows. (Esto es un poco de esfuerzo inicial, pero ahorra mucha angustia a largo plazo).
  3. Agregue más bloques try / catch e inicie sesión en la aplicación para obtener una mejor imagen de lo que está sucediendo.
McGarnagle
fuente
10
El Visor de eventos de Windows mostró el seguimiento completo de la pila, una herramienta muy útil.
Talha Imam
37

No estoy seguro de que esto sea útil, pero para depurar un servicio, siempre puede usar lo siguiente en el método OnStart:

protected override void OnStart(string[] args)
{
     System.Diagnostics.Debugger.Launch();
     ...
}

de lo que podría adjuntar su estudio visual al proceso y tener mejores habilidades de depuración.

espero que esto haya sido útil, buena suerte

Eyal H
fuente
Esta es, con mucho, la mejor solución (al menos para mí). VS 2015 también maneja esto muy bien. Para mí, apareció un cuadro de diálogo de confirmación de UAC para el depurador JIT y luego me dejó seleccionar VS 2015 como depurador.
Smitty
9

Me ha resultado muy útil convertir su servicio de Windows existente en una consola simplemente cambiando su programa con lo siguiente. Con este cambio, puede ejecutar el programa depurando en Visual Studio o ejecutando el ejecutable normalmente. Pero también funcionará como un servicio de Windows. También hice una publicación de blog al respecto.

program.cs

class Program
{
    static void Main()
    {
        var program = new YOUR_PROGRAM();
        if (Environment.UserInteractive)
        {
            program.Start();
        }
        else
        {
            ServiceBase.Run(new ServiceBase[]
            {
                program
            });
        }
    }
}

YOUR_PROGRAM.cs

[RunInstallerAttribute(true)]
public class YOUR_PROGRAM : ServiceBase
{
    public YOUR_PROGRAM()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        Start();
    }

    protected override void OnStop()
    {
        //Stop Logic Here
    }

    public void Start()
    {
        //Start Logic here
    }
}
Ben Anderson
fuente
2

EventLog.Log debe establecerse como "Aplicación"

panini pitke
fuente
Acabo de votar porque esta era en realidad la solución al problema para mí
Savage
1

Mientras tanto, otra razón: la eliminación accidental del archivo .config provocó que aparezca el mismo mensaje de error:

"El servicio en la computadora local se inició y luego se detuvo. Algunos servicios se detienen automáticamente ..."

Emre Guldogan
fuente
0

Utilice el temporizador y marque el evento para copiar sus archivos.

Al iniciar el servicio, inicie la hora y especifique el intervalo en la hora.

Por lo que el servicio sigue funcionando y copia los archivos con un solo clic.

Espero que te ayude.

Sethu
fuente
0

Es posible que desee realizar una prueba unitaria de la inicialización, pero debido a que está en el OnStart método, esto es casi imposible. Sugeriría mover el código de inicialización a una clase separada para que pueda probarse o al menos reutilizarse en un probador de formularios.

En segundo lugar, agregar algunos registros (usando Log4Net o similar) y agregar algunos registros detallados para que pueda ver detalles sobre los errores de tiempo de ejecución. Ejemplos de errores de tiempo de ejecución serían AccessViolationetc., especialmente si su servicio se ejecuta sin suficientes privilegios para acceder a los archivos de configuración.

Quinton Bernhardt
fuente
0

Es posible que la cuenta que ejecuta el servicio no haya asignado la unidad D: (son específicas del usuario). Intente compartir el directorio y use la ruta UNC completa en su backupConfig.

Su watchertipo FileSystemWatcheres una variable local y está fuera del alcance cuando OnStartse realiza el método. Probablemente lo necesite como una instancia o variable de clase.

Alf Kåre Lefdal
fuente
0

Me encontré con el mismo problema. Mi servicio está cargando / recibiendo XMLS y escribe los errores en el Registro de eventos.

Cuando fui al Registro de eventos, intenté filtrarlo. Me indica que el registro de eventos está dañado.

Borré el registro de eventos y todo bien.

PanosPlat
fuente
0

En nuestro caso, no se agregó nada en los registros de eventos de Windows, excepto los registros de que el servicio problemático se inició y luego se detuvo.

Resulta que el archivo CONFIG del servicio no era válido. La corrección del archivo CONFIG no válido solucionó el problema.

rikitikitik
fuente