WinForm 和 Windows Service 通信 消息队列

    技术2022-05-18  15

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

    一、建立工程

    建立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:windowsmicrosoft.netframeworkv2.0.50727InstallUtil.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:windowsmicrosoft.netframeworkv2.0.50727InstallUtil.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_MACHINEServicesCurrentControlSet      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_MACHINESYSTEM 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、卸载


    最新回复(0)