• C# 开发windows服务的一些心得


    最近在做一个windows服务的项目,发现并解决了一些问题,拿出来和大家分享一下,以下windows服务简称“服务”

    文章会在适合时间更新,因为朋友们在不断提出新的意见或思路,感谢~。~

    1.服务如何在某种情况下弹出一个窗体?

    第一种解决办法,用安装程序的代码修改注册表来完成:

    1.右击服务的视图设计界面的空白处,添加安装程序

    2.右击默认的serviceProcessInstaller1-->属性-->Account属性设置为LocalSystem

    3.右击安装程序空白处-->查看代码,添加以下代码

    public override void Install(IDictionary stateServer)
            {
                Microsoft.Win32.RegistryKey system, currentControlSet,services,    service, config;
    
                try
                {
                
                    base.Install(stateServer);
                    //打开注册表值
                    system = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System");
                    currentControlSet = system.OpenSubKey("CurrentControlSet");
                    services = currentControlSet.OpenSubKey("Services");
                    service = services.OpenSubKey(this.serviceInstaller1.ServiceName, true);
                    //设置服务的描述
                    service.SetValue("Description", "这是一个服务");
                    //允许服务与桌面交互
                    int value = (int)service.GetValue("Type");
                    service.SetValue("Type", value | 256);
                    config = service.CreateSubKey("Parameters");
                }
                catch (Exception e)
                {
                    Console.WriteLine("An exception was thrown during service installation:/n" + e.ToString());
                }
            }
    
            public override void Uninstall(IDictionary stateServer)
            {
                Microsoft.Win32.RegistryKey system,
                 currentControlSet,
                 services,
                 service;
    
                try
                {
                    //Drill down to the service key and open it with write permission
                    system = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System");
                    currentControlSet = system.OpenSubKey("CurrentControlSet");
                    services = currentControlSet.OpenSubKey("Services");
                    service = services.OpenSubKey(this.serviceInstaller1.ServiceName, true);
                    //Delete any keys you created during installation (or that your service created)
                    service.DeleteSubKeyTree("Parameters");
                    //...
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception encountered while uninstalling service:/n" + e.ToString());
                }
                finally
                {
                    //Let the project installer do its job
                    base.Uninstall(stateServer);
                }
            }

     这个方法很多,也可以在网上搜到

    第二种解决办法,用bat批处理文件修改注册表完成(如果已经运行的服务不是LocalSystem账户,是不允许与桌面交互的)

    创建一个bat文件,写入以下代码,保存并双击运行,点击 y 回车更改服务账户

    reg add HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServices自己服务的名称/v ObjectName /t REG_SZ /d LocalSystem

    如果想直接修改注册表,在以上代码前加"echo y|"   (没有双引号) 这样双击运行的时候就可以直接修改了

    第三种解决办法也是最简单的办法,通过手动修改

    打开服务控制器,右击要修改账户的服务属性,登录选项卡,修改为本地系统账户,并允许与桌面交互

     


    2.服务如何获取程序当前的路径?

    服务中使用Environment.CurrentDirectory获取的是system32的路径

    解决办法:添加引用:window.form

    使用Application.StartupPath(获取到程序生成的文件夹)

    (其它方法暂时还没有尝试,所以先不写了)


    3.如何使用Timer?

    和form不同,服务有专门的Timer

    右击工具箱"选择项",.netFrameWork组件:找到Timer

    别搞成Form里的Timer


     4服务的更新

    服务有时候出了问题也会用到更新,安装服务机子少时候可以自己手动更新,多的话,像上百台或更多,在做需求的时候就要想到更新程序是如此的重要

    我就是在这方面吃了大亏,请朋友们引以为戒

    如两个服务A和B,B是某某服务,A是B的更新服务,想要实现的功能:系统启动时自动启动A服务来检测B服务是否有更新文件,有则下载更新,启动B服务,无则直接启动B服务

    1.两个服务一定要分开两个项目来写,如果在一个项目里写两个服务,在更新的时候就会提示程序正在访问无法运行而更新失败

    2.B服务要设置为手动启动,如果早与A服务自动启动。并且A服务检测到有更新文件,将无法完成B服务的更新

    3.B服务设置为手动启动,并不是让你手动去启动B服务。是通过A来启动B。

    启动方式如下:

    条件:B服务为LocalSystem,并且B服务已经安装完成

    利用进程启动B服务

    public void RunService()
            {
                Process PortProcess = new Process();
                PortProcess.StartInfo.FileName = "cmd.exe";
                PortProcess.StartInfo.UseShellExecute = false;
                PortProcess.StartInfo.RedirectStandardInput = true;
                PortProcess.StartInfo.RedirectStandardOutput = true;
                PortProcess.StartInfo.RedirectStandardError = true;
                PortProcess.StartInfo.CreateNoWindow = true;
                try
                {
                    PortProcess.Start();
                    PortProcess.StandardInput.WriteLine("net start 服务的名称");
                    PortProcess.StandardInput.WriteLine("exit");
                    PortProcess.Close();
                }
                catch (Exception)
                {
                }
            }

    其它方式有待改进,暂不贴出


    5服务的调试

    个人知道的有两种服务调试的方式

    1是用VS,附加到进程来做调试,步骤比较简单但也有缺点

    (1)安装和启动一个服务以后,点击VS中的调试-->附加到进程(注意选择"附加到"这个选项,一定要是自己程序的代码,我用的.net4.0,所以我选择的是"托管4.0版代码")

    (2)找到自己的程序进程,附加即可

    这种方式的缺点:因为是在启动以后才可以附加到进程.服务的OnStart方法无法调试。所以我一般都会把代码放到OnStop方法里调试

    2是做调试日志,每个步骤写日志的方式来检测服务是否正常启动等(我一直没用过,暂无介绍)不过个人认为这种方式也会有缺点.没有断点调试那样直观

    不过有机会可以试试这种方式


    多说都是泪,方法和思路都是自己试出来的,有什么代码或思路错误请朋友们提出,对的点个赞,谢谢~

    感谢区:

    由于不知道怎么把评论人的名字搞到这里来,所以只能这样感谢你们提出的意见了,谢谢~.~

  • 相关阅读:
    第二十三章 kubernetes 核心技术Volume
    第二十一章 kubernetes核心技术Ingress
    第十九章 kubernetes 核心技术ConfigMap
    vuejs在解析时出现闪烁的原因及防止闪烁的方法
    2020/9/5
    2021/9/3
    2021/9/7
    2021/9/2
    2021/9/4
    2021/9/6
  • 原文地址:https://www.cnblogs.com/luke1006/p/4001608.html
Copyright © 2020-2023  润新知