现在的位置: 首页 > 综合 > 正文

WinForm 和 Windows Service 通信

2014年09月05日 ⁄ 综合 ⁄ 共 13588字 ⁄ 字号 评论关闭

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

 

http://www.cnblogs.com/newspring/articles/1357733.html

抱歉!评论已关闭.