您的位置:首页 > 编程语言 > C#

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

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、卸载

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