本地计算机上的Windows服务启动后立即停止错误。

116
通常,我会遇到这个错误:(“服务名称”服务在本地计算机上启动然后停止。如果某些服务未被其他服务或程序使用,则某些服务将自动停止),当我的代码出现问题时,例如不存在的驱动路径等。Windows服务将无法启动。
我有一个Windows服务,用于备份文件/文件夹到一定大小时的位置。所有详细信息都由XML配置提供,Windows服务在启动时读取。我有一个单独的Windows表单,其中有一个按钮可以执行与我的Windows服务OnStart相同的操作,我使用我的Windows表单来调试代码,然后再将其放入我的Windows服务中。
当我启动我的Windows表单时,它会执行其应该执行的操作。但是,当我将我的代码放入Windows服务的OnStart()方法中时,就会出现错误。
以下是我的代码:
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();
        }
    }
我不知道是什么原因导致了Windows服务无法启动,而Windows表单模拟器却可以正常工作。问题出在哪里?
更新: 经过多次尝试,我注意到,如果只使用文件夹路径(没有文件),则Windows服务将无法正常工作。当我用特定的文件(包括其路径)替换fileWatch变量时,Windows服务就能够启动。当我把它改回文件夹位置时,它就无法正常工作。我的想法是,文件夹位置在文件监视器中无法正常工作。
当我尝试创建一个新的Windows服务来监视文件夹位置时,它可以正常工作。但是,当我在我的原始Windows服务中尝试相同的位置时,它就不能工作!这让我很困惑!看来我必须每次放置新的代码/函数时都要创建一个新的Windows服务并构建安装程序。这样我就可以追踪到错误发生的地方。
11个回答

221

如果服务启动并且停止,那么这意味着您的代码抛出了一个未处理的异常。这很难进行调试,但有几个选项。

  1. 查看 Windows 事件查看器。通常可以通过转到计算机/服务器管理器,然后单击 事件查看器 -> Windows 日志 -> 应用程序 来访问它。您可以在此处查看抛出异常的原因,这可能有所帮助,但您无法获得堆栈跟踪。
  2. 将程序逻辑提取到库类项目中。现在创建两个不同版本的程序:控制台应用程序(用于调试)和 Windows 服务。(这需要一些初始工作,但从长远来看可以节省很多烦恼。)
  3. 添加更多的 try/catch 块和日志记录到应用程序中,以便更好地了解情况。

14
Windows 事件查看器显示了完整的堆栈跟踪,这是一个非常有用的工具。 - Talha Imam
非常感谢。最近我卸载了JRE,但是无法重新启动Jenkins服务,因为它指向已删除的JRE bin目录。不得不在jenkins.xml文件的executable标签中配置新路径。我发现这个答案真的很有帮助!+1。 - Jay

37

我不确定这会有帮助,但是为了调试服务,您可以在OnStart方法中始终使用以下内容:

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

你可以将你的Visual Studio附加到该进程上以获得更好的调试能力。

希望这对你有所帮助,祝你好运。


这绝对是最好的解决方案(至少对我来说是)。VS 2015 也很好地处理了这个问题。对我来说,它弹出了一个 UAC 确认对话框,让我选择 VS 2015 作为调试器。 - Smitty

9
我发现将现有的 Windows服务 转换为 控制台 非常方便,只需通过以下方式更改程序即可。通过此更改,您可以在Visual Studio中进行调试或正常运行可执行文件。但它也可以作为Windows服务工作。我也写了一篇博客文章介绍这个过程

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
    }
}

4

2

应将EventLog.Log设置为“Application”


我刚刚点赞了,因为这对我来说确实是解决问题的方法。 - Savage

1
同时,另一个原因:意外删除了.config文件会导致出现相同的错误信息:

"本地计算机上的服务已启动,然后停止。一些服务自动停止..."


0

使用计时器和tick事件来复制您的文件。

启动服务时,启动时间并指定时间间隔。

因此,服务保持运行并在ontick时复制文件。

希望能够帮助你。


0

你可能想对初始化进行单元测试,但因为它在OnStart方法中,这几乎是不可能的。我建议将初始化代码移到一个单独的类中,以便可以进行测试或至少在表单测试器中重复使用。

其次,添加一些日志记录(使用Log4Net或类似工具),并添加一些详细的日志记录,以便您可以查看有关运行时错误的详细信息。运行时错误的示例包括AccessViolation等,特别是如果您的服务在没有足够权限访问配置文件的情况下运行。


0

正在运行服务的帐户可能没有映射 D: 驱动器(它们是用户特定的)。尝试共享目录,并在您的 backupConfig 中使用完整的 UNC 路径。

您的类型为 FileSystemWatcherwatcher 是一个局部变量,在 OnStart 方法完成时已经超出作用域。您可能需要将其作为实例或类变量。


0
在我们的情况下,除了记录有问题服务已启动然后停止的日志之外,在Windows事件日志中没有添加任何内容。
事实证明,服务的CONFIG文件无效。纠正无效的CONFIG文件解决了问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接