再努力一点点

没有烟抽的日子
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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;
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;
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改成绝对路径。