windows服务发布过程中遇到问题的原因分析及解决方式

本文介绍了一种双Shell应用模式,在此模式下通过一个LibraryLib和两个Shell(EAI.WinForm.App与EAI.WinService)实现服务的配置与运行。文章详细描述了在服务Shell开发过程中遇到的问题及解决方案,特别是关于配置文件读取路径和异常处理的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在最近的一个应用项目中,采用了双Shell的应用模式,即采用一个LirabaryLib,2Shell,同时打包在一个应用安装包中,部署之后,EAI.WinForm.App这个窗体Shell用来设置若干服务相关的运行参数,EAI.WinService这个服务Shell用来依据包含参数设置内容的配置文件来后台运行这些服务.结构如下图:

部署结构

 

由于优先开发的窗体Shell,所以在后来的服务Shell开发过程中,为了充分复用源码,采用了如下构造方式:

1.开放窗体Shell的服务启动和服务停止入口方法为public;

2.在服务ShellOnStart方法中进行类似下面的编码:

  Executor = new EAI.WinForm();

  Executor.RunService();

3.在服务ShellOnStop方法中进行类似下面的编码:

  Executro.StopService();

4.Executor.RunService()的实现包含类似下面的编码:

     //写启动日志

     //读取当前目录中的配置文件

     //从配置文件中创建需要加载的服务组件实例

     //写进度日志

     //为服务实例包装一个多线程运行器(System.Threading.Timer)

     //依据配置文件的配置时点设置多线程运行器的激发时点和周期

     //写成功日志

最后,在调式的过程中,发现在服务Shell的运行过程中,启动日志和成功日志被成功写入,但是无论怎样配置config.xml中相关的服务激发时点,都没有服务组件运行的迹象发生。

无奈,创建了一个Console(控制台项目)对OnStart中的代码进行移植,单步跟踪,发现了如下问题:

  void Worker_OnSyncException(ExecutorExceptionEventArgs e)

        {           

            BeginInvoke(WriteLogHandler, new object[] { new System.Text.StringBuilder().Append(e.Service.Name).Append("运行错误:/r/n").Append(e.Exception.Message).ToString() });

        }

上述代码在调用中报告错误,原因是没有主窗体(上述代码是EAI.WinForm中的实现,由于相应事件中的写日志方法处在一个并行运行的环境中,因此采用BeginInvoke方式进行方法调用),原来在调用代码中确实没有进行Executor.Show()操作,所以导致以上异常,遂进行以下改造:

void Worker_OnSyncException(ExecutorExceptionEventArgs e)

        {

            if (System.Windows.Forms.Application.OpenForms.Count == 0)

            {

                WriteLog(new System.Text.StringBuilder().Append(e.Service.Name).Append("运行错误:/r/n").Append(e.Exception.Message).ToString());

            }

            else

            {

                BeginInvoke(WriteLogHandler, new object[] { new System.Text.StringBuilder().Append(e.Service.Name).Append("运行错误:/r/n").Append(e.Exception.Message).ToString() });

            }

        }

确保在非窗体运行环境中可以正确调用写日志操作.继续调试,Console(控制台项目)中服务组件能够被正确定时激活.于是继续回到服务Shell环境中进行测试,发现服务Shell环境中服务组件依旧不能被正确定时激活,无奈之下,分析原因,唯一可能出问题的地方就是读取当前目录中的配置文件方法在Windows.Form环境下和Windows.Service环境下可能存在区别,于是将System.Environment.CurrentDirectory方法替换为System.Windows.Forms.Application.StartupPath,再调试,成功,原来System.Environment.CurrentDirectoryWindow.Form环境下Windows.Form环境下和Windows.Console环境下能够获取当前运行目录,而在Windows.Service环境下却获取的是Windows/System32目录,难怪服务组件不能被正确定时激活,因为没有读取到相关的配置文件,应用代码没有加载任何的服务组件实现。

Ps:容错性很高,但是可用性不是太好,呵呵。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值