您的位置:首页 > 其它

WinForm 和 Windows Service 通信 - 消息队列

2008-12-18 18:34 323 查看
如题,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、卸载

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐