zoukankan      html  css  js  c++  java
  • C#winform windows服务程序创建与安装

     

    如题,WinForm 和 Windows Service 通信,就是应用程序和系统服务通信,可以看成是进程间的通信。通信的方式有很多,这里只介绍通过消息队列(MessageQueue)方式。理论知识就不介绍了,直接介绍实例吧。

    工程下载 /Files/newspring/WindowsService.rar 

    一、建立工程

    建立3个项目,其中,

    Common 为类库,包含错误日志类(Log.cs)和数据库访问类(MsSql.cs)

    ServiceDemo 为Windows Service服务,包含安装类(Installer1.cs)和服务类(Service1.cs)

    ServiceDesk 为WinForm应用程序,包含一个主窗口类(frmMain.cs)

    这3个项目要实现的功能是,进程间通信,具体怎么通信呢?这里我设计的是用ServiceDesk这个WinForm实时监控ServiceDemo这个系统服务。ServiceDesk和ServiceDemo之间的通信就通过消息队列(MessageQueue)方式。

    对了,补充下理论,消息队列必须安装后才能用,安装步骤如下:

    控制面板->添加或删除程序->添加或删除组件

    选择应用程序服务器详细信息

    勾上消息队列

    安装完就可以通过控制面板->管理工具->计算机管理->服务和应用程序访问了

    二、书写服务

    Service1.cs

    public partial class Service1 : ServiceBase
        {
            Thread m_thread1;

            public Service1()
            {
                InitializeComponent();
            }

            protected override void OnStart(string[] args)
            {
                if (m_thread1 != null && m_thread1.ThreadState != System.Threading.ThreadState.Aborted)
                {
                    m_thread1.Abort();
                }

                m_thread1 = new Thread(new ThreadStart(Work));
                m_thread1.IsBackground = true;
                m_thread1.Start();
            }

            protected override void OnStop()
            {

            }

            private void Work()
            {
                while (true)
                {
                    //try
                    //{
                    //    string sql = "insert into T_Log(DateTime,Description)values('{0}','{1}')";
                    //    sql = String.Format(sql, DateTime.Now.ToString(), "adsf");

                    //    int Result = Common.MsSql.ExecuteNonQuery(sql, this.GetType());
                    //}
                    //catch (Exception e)
                    //{
                    //    Common.Log.Write(e);
                    //}


                    string msg = "消息内容测试";
                    SendMessage(msg);

                    System.Threading.Thread.Sleep(500);
                }
            }

            void SendMessage(string msg)
            {
                try
                {
                    string QueuePath = ".\\private$\\aaaa";
                    MessageQueue MQueue;

                    if (!MessageQueue.Exists(QueuePath))
                    {
                        return;
                    }

                    MQueue = new MessageQueue(QueuePath);

                    System.Messaging.Message Msg = new System.Messaging.Message();
                    Msg.Body = msg;

                    //XML格式化传输量较大
                    //Msg.Formatter = new System.Messaging.XmlMessageFormatter(new Type[] { typeof(string) });
                    Msg.Formatter = new System.Messaging.BinaryMessageFormatter();
                    MQueue.Send(Msg);
                }
                catch (Exception ex)
                {
                    Common.Log.Write(this.GetType(), ex);
                }
            }
        }

    三、书写服务控制(WinForm)

    frmMain.cs

    简单界面

    其中组件引用:

    serviceController1的ServiceName属性设置为 ServiceDemo

    代码:

    public partial class frmMain : Form
        {
            int i = 1;
            Thread t1;
            Thread t2;

            string QueuePath = ".\\private$\\aaaa";

            public frmMain()
            {
                InitializeComponent();
            }

            private void frmMain_Load(object sender, EventArgs e)
            {
                this.notifyIcon1.Icon = new Icon("E:\\WorkSpace\\WindowsService\\ServiceDesk\\Resources\\Icon1.ico");

                frmMain.CheckForIllegalCrossThreadCalls = false;

                t1 = new Thread(new ThreadStart(PrintServiceStatus));
                t1.Start();
            }

            private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
            {
                this.Visible = true;
                this.WindowState = FormWindowState.Normal;
            }
               
            private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
            {
                //取消关闭窗口
                e.Cancel = true;
                //将窗口最小化
                this.WindowState = FormWindowState.Minimized;
                //将窗口隐藏
                this.Visible = false;
            }

            private void toolStripMenuItem1_Click(object sender, EventArgs e)
            {
                this.Visible = true;
                this.WindowState = FormWindowState.Normal;
            }

            private void ToolStripMenuItem2_Click(object sender, EventArgs e)
            {
                notifyIcon1.Visible = false;
               
                Application.Exit();
            }

            /// <summary>
            /// 继续
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void toolStripMenuItem_Continue_Click(object sender, EventArgs e)
            {

            }

            /// <summary>
            /// 执行Cmd命令
            /// </summary>
            public void Cmd(string c)
            {
                System.Diagnostics.Process process = new System.Diagnostics.Process();
                process.StartInfo.FileName = "cmd.exe";
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardInput = true;
                process.Start();

                process.StandardInput.WriteLine(c);
                process.StandardInput.AutoFlush = true;
                process.StandardInput.WriteLine("exit");
               
                StreamReader reader = process.StandardOutput;//截取输出流
               
                string output = reader.ReadLine();//每次读取一行
               
                while (!reader.EndOfStream)
                {
                    PrintThrendInfo(output);
                    output = reader.ReadLine();
                }

                process.WaitForExit();
            }

            #region 进度显示
            private void PrintThrendInfo(string Info)
            {
                lock (listView1)
                {
                    try
                    {
                        ListViewItem Item = new ListViewItem(i.ToString());
                        Item.SubItems.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        Item.SubItems.Add(Info);
                        listView1.Items.Add(Item);
                        //listView1.RedrawItems(i - 1, i - 1, false); //线程中不能用这句
                        i++;
                        if (i >= 1000)
                        {
                            listView1.Items.Clear();
                            i = 1;
                        }
                    }
                    catch (SystemException ex)
                    {
                        Log.Write(this.GetType(),ex);
                    }
                }
            }

            private void PrintThrendInfo(string Info, Color ForeColor)
            {
                //锁定资源
                lock (listView1)
                {
                    try
                    {
                        ListViewItem Item = new ListViewItem(i.ToString());
                        Item.SubItems.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        Item.SubItems.Add(Info);
                        listView1.Items.Add(Item);
                        Item.ForeColor = ForeColor;
                        if (ForeColor == Color.Red || ForeColor == Color.Fuchsia)
                        {
                            Log.Write(this.GetType(), Info);
                        }
                        //listView1.RedrawItems(i - 1, i - 1, false); //线程中不能用这句
                        i++;
                        if (i >= 10000)
                        {
                            listView1.Items.Clear();
                            i = 1;
                        }
                    }
                    catch (SystemException ex)
                    {
                        Log.Write(this.GetType(),ex);
                    }
                }
            }
            #endregion

            /// <summary>
            /// 安装
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnInstall_Click(object sender, EventArgs e)
            {
                try
                {
                    t2.Abort();
                }
                catch { }

                t2 = new Thread(new ThreadStart(Install));
                t2.Start();
            }

            void Install()
            {
                t1.Suspend();
                string c = @"c:\windows\microsoft.net\framework\v2.0.50727\InstallUtil.exe " + AppDomain.CurrentDomain.BaseDirectory + "ServiceDemo.exe";
                Cmd(c);
                t1.Resume();
            }

            /// <summary>
            /// 卸载
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnUninstall_Click(object sender, EventArgs e)
            {
                try
                {
                    t2.Abort();
                }
                catch { }

                t2 = new Thread(new ThreadStart(Uninstall));
                t2.Start();
            }

            void Uninstall()
            {
                t1.Suspend();
                string c = @"c:\windows\microsoft.net\framework\v2.0.50727\InstallUtil.exe /u " + AppDomain.CurrentDomain.BaseDirectory + "ServiceDemo.exe";
                Cmd(c);
                t1.Resume();
            }

            /// <summary>
            /// 启动
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnStart_Click(object sender, EventArgs e)
            {
                try
                {
                    t2.Abort();
                }
                catch { }

                t2 = new Thread(new ThreadStart(Start));
                t2.Start();
            }

            void Start()
            {
                t1.Suspend();
                string c = @"net start ServiceDemo";
                Cmd(c);
                t1.Resume();
            }

            /// <summary>
            /// 停止
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnStop_Click(object sender, EventArgs e)
            {
                try
                {
                    t2.Abort();
                }
                catch { }

                t2 = new Thread(new ThreadStart(Stop));
                t2.Start();
            }

            void Stop()
            {
                t1.Suspend();
                string c = @"net stop ServiceDemo";
                Cmd(c);
                t1.Resume();
            }

            private void PrintServiceStatus()
            {
                if (MessageQueue.Exists(QueuePath))
                {
                    MessageQueue.Delete(QueuePath);
                }

                while (true)
                {
                    t1.Join(1000);

                    this.serviceController1.Refresh();

                    if (this.serviceController1.Status != ServiceControllerStatus.Running)
                    {
                        PrintThrendInfo("服务运行状态:" + this.serviceController1.Status.ToString());

                        if (MessageQueue.Exists(QueuePath))
                        {
                            MessageQueue.Delete(QueuePath);
                        }

                        continue;
                    }

                    MessageQueue MQueue;

                    if (MessageQueue.Exists(QueuePath))
                    {
                        MQueue = new MessageQueue(QueuePath);
                    }
                    else
                    {
                        MQueue = MessageQueue.Create(QueuePath);
                        MQueue.SetPermissions("Administrators", MessageQueueAccessRights.FullControl);
                        MQueue.Label = QueuePath;
                    }

                    //一次读一条,取一条自动去掉读取的这一条
                    //System.Messaging.Message Msg = MQueue.Receive(new TimeSpan(0, 0, 2));

                    //一次读取全部消息,但是不去除读过的消息
                    System.Messaging.Message[] Msg = MQueue.GetAllMessages();
                    //删除所有消息
                    MQueue.Purge();

                    foreach (System.Messaging.Message m in Msg)
                    {
                        //XML格式化传输量较大
                        //Msg.Formatter = new System.Messaging.XmlMessageFormatter(new Type[] { typeof(string) });

                        m.Formatter = new System.Messaging.BinaryMessageFormatter();
                        PrintThrendInfo(m.Body.ToString());
                    }
                }
            }
        }

    三、制作安装

    Installer1.cs

    [RunInstaller(true)]
        public partial class Installer1 : Installer
        {
            public Installer1()
            {
                InitializeComponent();
            }

            public override void Install(IDictionary stateSaver)
            {
                Microsoft.Win32.RegistryKey system;
                    //HKEY_LOCAL_MACHINE\Services\CurrentControlSet
                Microsoft.Win32.RegistryKey currentControlSet;
                    //...\Services
                Microsoft.Win32.RegistryKey services;
                            //...\<Service Name>
                Microsoft.Win32.RegistryKey service;
                            //...\Parameters - this is where you can put service-specific configuration
                Microsoft.Win32.RegistryKey config;
                try
                {
                    //Let the project installer do its job
                    base.Install(stateSaver);

                    //Open the HKEY_LOCAL_MACHINE\SYSTEM key
                    system = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System");
                    //Open CurrentControlSet
                    currentControlSet = system.OpenSubKey("CurrentControlSet");
                    //Go to the services key
                    services = currentControlSet.OpenSubKey("Services");
                    //Open the key for your service, and allow writing
                    service = services.OpenSubKey(this.serviceInstaller1.ServiceName, true);
                    //Add your service's description as a REG_SZ value named "Description"
                    service.SetValue("Description", "计划按时执行,如一分钟一次");
                    //(Optional) Add some custom information your service will use...
                    //允许服务与桌面交互
                    service.SetValue("Type", 0x00000110);
                    config = service.CreateSubKey("Parameters");
                }
                catch (Exception e)
                {
                    Console.WriteLine("An exception was thrown during service installation:\n" + e.ToString());
                }
            }

            public override void Uninstall(IDictionary savedState)
            {
                Microsoft.Win32.RegistryKey system;
                Microsoft.Win32.RegistryKey currentControlSet;
                Microsoft.Win32.RegistryKey services;
                Microsoft.Win32.RegistryKey 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(savedState);
                }
            }
        }

    四、运行效果

    1、安装效果

    2、运行

    3、卸载

  • 相关阅读:
    gitlab第一次提交
    Command 'cnpm' not found解决方法
    ubuntu18.04安装sublime
    django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured.
    django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named 'MySQLdb'. Did you install mysqlclient or MySQL-python?
    ubuntu18.04安装MySQL
    ubuntu18.04彻底卸载mysql
    rabbitmq高可用
    ASP.NET Global.asax详解
    如何真正提高ASP.NET网站的性能
  • 原文地址:https://www.cnblogs.com/xiaofengfeng/p/2193952.html
Copyright © 2011-2022 走看看