如题,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://lib.csdn.net/article/csharp/44879