WinForm 和 Windows Service 通信 消息队列

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

一、建立工程

建立3个项目,其中,

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

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

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

WinForm 和 Windows Service 通信 消息队列_第1张图片

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

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

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

WinForm 和 Windows Service 通信 消息队列_第2张图片

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

WinForm 和 Windows Service 通信 消息队列_第3张图片

勾上消息队列

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

WinForm 和 Windows Service 通信 消息队列_第4张图片

二、书写服务

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

简单界面

WinForm 和 Windows Service 通信 消息队列_第5张图片

其中组件引用:

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();
        }

        ///


        /// 继续
        ///

        ///
        ///
        private void toolStripMenuItem_Continue_Click(object sender, EventArgs e)
        {

        }

        ///


        /// 执行Cmd命令
        ///

        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

      ///


    /// 安装
    ///

    ///
    ///
    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();
    }
  
    ///
    /// 卸载
    ///

    ///
    ///
    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();
    }
  
    ///
    /// 启动
    ///

    ///
    ///
    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();
    }
  
    ///
    /// 停止
    ///

    ///
    ///
    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;
            //...
      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、卸载

你可能感兴趣的:(Windows相关)