Batch Script to Install or Uninstall a .NET Windows Service
Posted on 2010-06-01 18:20 ZhangPeng.Chen 阅读(881) 评论(0) 收藏 举报Windows批处理文件,批处理文件的扩展名为.bat或.cmd。在命令行提示下键入批处理文件的名称,或者双击批处理文件,系统就会调用Cmd.exe按照该批处理文件中各个命令的顺序依次执行。
1.
运行Cmd
键入命令: echo Hello World
结果:Hello World
可见echo是输出命令,相当于Console.WriteLine("Hello World")
2.
HelloWorld.bat
echo Hello World
双击运行
结果:一闪而过,因为我们的命令被执行结束,所以就直接被退出了。
加个pause命令表示暂停。
3.
HelloWorld.bat
echo Hello World
pause
结果:
echo Hello World
Hello World
请按任意键结束 (后面我都省略)
默认Cmd.exe每读取一条命令都会将其显示出来,所以我们所执行的使命echo Hello World也被显示出来了。(称为回显)
有的时候我们并不想让用户知道我们执行了哪些命令,那我们可以关闭回显。
4.
HelloWorld.bat
@echo Hello World
pause
双击运行
结果:
Hello World
说明@可以关闭当前命令的回显,那要是有100条命令,每个命令前都加上,不死人才怪。
5.
HelloWorld.bat
@echo off
echo Hello World
echo Hello World
pause
双击运行
结果:
Hello World
Hello World
说明@echo off可以为所有命令关闭回显
-------------------------------------------------------------- 下面将用到的批命令介绍结束
新建一个Windows Service项目,添加HelloWorldService
Program.cs代码:
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
namespace HelloWorld
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] services = new ServiceBase[] {
new HelloWorldService()
};
ServiceBase.Run(services);
}
}
}
使用System.ServiceProcess下的ServiceBase运行我们需要在Windows上跑的Service
HelloWorldService.cs代码:
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;
using System.Threading;
namespace HelloWorld
{
public partial class HelloWorldService : ServiceBase
{
public HelloWorldService()
{
InitializeComponent();
}
private Thread thread;
protected override void OnStart(string[] args)
{
Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
Log("Start HelloWorldService");
thread = new Thread(new ThreadStart(Run));
thread.Priority = ThreadPriority.Normal;
thread.Start();
}
private static void Run()
{
while (true)
{
Log(DateTime.Now.ToString());
Thread.Sleep(1000);
}
}
protected override void OnStop()
{
Log("Stop HelloWorldService");
}
private static void Log(string message)
{
string path = string.Format(@"{0}\{1}.txt",
Directory.GetCurrentDirectory(),
DateTime.Today.ToString("yyyy-MM-dd"));
using (StreamWriter streamWriter = new StreamWriter(path, true))
{
streamWriter.WriteLine(message);
}
}
}
}
Service必须继承至System.ServiceProcess下的ServiceBase,Windows Service中使用AppDomain.CurrentDomain.BaseDirectory、Directory.GetCurrentDirectory()等默认都会被跳到C:\Windows\System32目录中,所以我们需要在OnStart中设置一下CurrentDirectory。
-------------------------------------------------------------- 批处理文件
Install.bat
@echo off
echo install start....
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\installutil.exe /i HelloWorld.exe
Net Start "HelloWorldService"
pause
这里 /i 表示安装HelloWorld.exe这个程序,Net Start表示启动HelloWorldService
Uninstall.bat
@echo off
echo uninstall start....
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\installutil.exe /u MailSender.exe
pause
这里 /u 表示卸载HelloWorld.exe这个程序,Net Stop就不用了,都被卸载是不。
-------------------------------------------------------------- 可能出现的问题
1. 无法安装,提示RunInstaller(true)...
原因,未提供安装包,在HelloWorldService的设计器上右键Add Installer,会产生一个ProjectInstaller.cs文件
2. 打开ProjectInstaller.cs设计器
默认HelloWorldService的安装实例helloWorldServiceInstaller和serviceProcessInstaller会被加入,名字自己取。。。
3. helloWorldServiceInstaller配置StartType为Automatic这会为自动启动,比较方便。
4. 默认启动该服务,会弹出用户登录框,需要验证。
将serviceProcessInstaller的Account设置为LocalSystem
--------------------------------------------------------------- Windows7下可能出现的问题
直接双击Instal.bat这个批处理文件,会提示System.Security.SecurityException,提示创建EventLog时抛出(安全异常,通常由权限不够导致)
说明当我们运行这个批处理文件时,由于无创建EventLog的权限导致了这个异常。
HelloWorldService中并没有创建EventLog的代码,所以可能的问题应该在ServiceBase中。
查看ServiceBase发现使用了EventLog相关代码,我们可以在事件查看器中看到相关的信息。在Windows7下,非管理员无此权限。
我们已经自己使用了Log,所以EventLog已经没有必要了。可以设置AutoLog为false不进行Log。(不过设置了,结果还是一样,还是会进行创建EventLog,不知道如何关掉,郁闷。)
这个方法行不通只能使用以管理员的方式执行批处理文件了,然后把批处理文件中的HelloWorld.exe改成绝对路径。