zoukankan      html  css  js  c++  java
  • WinForm 和 Windows Service 通信 消息队列(转)

    原链接:http://www.cnblogs.com/newspring/archive/2008/12/18/1357735.html

    如题,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、卸载

  • 相关阅读:
    使用MobaXterm远程连接Ubuntu,启动Octave,界面不能正常显示
    ABP .Net Core 日志组件集成使用NLog
    ABP .Net Core Entity Framework迁移使用MySql数据库
    ABP前端使用阿里云angular2 UI框架NG-ZORRO分享
    阿里云 Angular 2 UI框架 NG-ZORRO介绍
    Visual Studio 2019 Window Form 本地打包发布猫腻
    VS Code + NWJS(Node-Webkit)0.14.7 + SQLite3 + Angular6 构建跨平台桌面应用
    ABP .Net Core 调用异步方法抛异常A second operation started on this context before a previous asynchronous operation completed
    ABP .Net Core To Json序列化配置
    .Net EF Core数据库使用SQL server 2008 R2分页报错How to avoid the “Incorrect syntax near 'OFFSET'. Invalid usage of the option NEXT in the FETCH statement.”
  • 原文地址:https://www.cnblogs.com/glacier/p/1423529.html
Copyright © 2011-2022 走看看