C# winform windows服务安装与卸载
2016-05-21 16:50
357 查看
如题,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
三、书写服务控制(WinForm)
frmMain.cs
简单界面
其中组件引用:
serviceController1的ServiceName属性设置为 ServiceDemo
代码:
三、制作安装
Installer1.cs
四、运行效果
1、安装效果
2、运行
3、卸载
工程下载 /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("Par 9055 ameters"); } 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、卸载
相关文章推荐
- C# Log4Net使用示例
- 对数组的每个元素仍是数组的遍历方法,c#,foreach,for
- CLR Via C# 第五章(基元类型,引用类型与值类型)(1)——读书笔记
- C#—Windows应用基础2
- C#中系统时间和UNIX时间戳互相转换
- C#操作XML
- C# 委托的三种调用示例(同步调用 异步调用 异步回调)
- c#使用easyhook库进行API钩取
- 有关C#标签Attribute的熟悉
- 20个C#热点问题
- C#中组件与控件的主要区别是什么
- c#根据当前系统时间生成的随机序列数
- 数组,C#
- c#窗体控件datagriview与dataset的运用:修改,新增,删除,查找,保存,更新
- IF-ELSE IF-ELSE语句
- C# 常忘知识
- C# 字符串string和内存流MemoryStream及比特数组byte[]之间相互转换
- C#下汉字转换成拼音
- C#迭代器
- 简单实现DevExpress换肤