增加一个服务:
[Version]
Signature="$WINDOWS NT$"
[DefaultInstall.Services]
AddService=myTest,,My_AddService_Name
[My_AddService_Name]
DisplayName=myTest
Description=myTest服务。
ServiceType=0x10
StartType=2
ErrorControl=0
ServiceBinary=%11%myTest.exe
保存为inetsvr.inf,然后在运行里注册该文件:
rundll32.exe setupapi,InstallHinfSection DefaultInstall 128 c:\path\myTestRegister.inf
这个例子增加一个名为myTest.的服务.
//////////////////
几点说明:
1,最后四项分别是
服务类型:0x10为独立进程服务,0x20为共享进程服务(比如svchost);
启动类型:0 系统引导时加载,1 OS初始化时加载,2 由SCM(服务控制管理器)自动启动,3 手动启动,4 禁用。
(注意,0和1只能用于驱动程序)
错误控制:0 忽略,1 继续并警告,2 切换到LastKnownGood的设置,3 蓝屏。
服务程序位置:%11%表示system32目录,%10%表示系统目录(WINNT或Windows),%12%为驱动目录system32drivers。
其他取值参见DDK。你也可以不用变量,直接使用全路径。
这四项是必须要有的。
2,除例子中的六个项目,还有LoadOrderGroup、Dependencies等。不常用所以不介绍了。
3,inetsvr后面有两个逗号,因为中间省略了一个不常用的参数flags。
删除一个服务:
[Version]
Signature="$WINDOWS NT$"
[DefaultInstall.Services]
DelService=inetsvr
很简单,不是吗?
当然,你也可以通过导入注册表达到目的。但inf自有其优势。
1,导出一个系统自带服务的注册表项,你会发现其执行路径是这样的:
"ImagePath"=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,
74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,74,
00,6c,00,6e,00,74,00,73,00,76,00,72,00,2e,00,65,00,78,00,65,00,00,00
可读性太差。其实它就是%SystemRoot%system32 lntsvr.exe,但数据类型是REG_EXPAND_SZ。当手动导入注册表以
增加服务时,这样定义ImagePath显然很不方便。而使用inf文件就完全没有这个问题,ServiceBinary(即ImagePath)
自动成为REG_EXPAND_SZ。
2,最关键的是,和用SC等工具一样,inf文件的效果是即时起效的,而导入reg后必须重启才有效。
3,inf文件会自动为服务的注册表项添加一个Security子键,使它看起来更像系统自带的服务。
另外,AddService和DelService以及AddReg、DelReg可以同时且重复使用。即可以同时增加和删除多个服务和注册表项。
--------------------------------------------------------------------------------------------------------------------------------------
方法二:用C#调用myTest.exe, 生成服务
Note: **这个方法试验成功了,可以启动也可以停止服务(可是看不到exe的运行界面:()**
(1).先用C#建立一个"Window服务"专案myTestService,
在WatchFile.cs界面上拖两个控件:fileSystemWatcher1和eventLog1,
设置fileSystemWatcher的属性-filter为"myTest.exe"及path(监控myTest.exe是否被修改),
eventLog1的source设置为fileSystemWatcher1;
然后点属性窗口的"加入安装程式",
会创建一个新页面ProjectInstaller.cs,设置此页面界面上的serviceProcessInstaller1的account属性为LocalSystem,serviceInstaller1的设置是和服务相关的,如StartType设为Automatic自动运行,
DisplayName为myTestService1是生成的服务的名子。。。
(2).编写WatchFile.cs程式(见后面)
(3).建置,在专案的bin\debug下得到一个myTestService.exe
然后在.NET的命令提示字元里,进入这个专案的bin\debug,
安装服务:installutil myTestService.exe
卸除服务:install /u myTestService.exe(先停止服务再卸)
也可以创建安装文件:
加入一个安装专案TestSetup,
点右键:加入->专案输出(选择主要输出),
然后再点右键:检视->自定动作(按此的右键)->应用程序资料夹->加入里面的东东
建置此专案,在TestSetup文件夹的Debug下会有安装文件,安装就可以了
(4). 安装后,在控制面板的服务里看到服务myTestService1已经有了,
可以启动和停止测看看exe启动没有(在进程里看),也可以查看电脑的应用程序日志文件看程式里的打印信息
主要程式如下:
//////////////////
WatchFile.cs的程式: 主要是OnStart和OnStop
========OnStart启动服务========
protected override void OnStart(string[] args)
{
try
{
eventLog1.WriteEntry("[myTest Info]: Start begin!"); //记录在应用程序日志里
Process[] testService_processNames=Process.GetProcessesByName(System.Diagnostics.Process.GetCurrentProcess().ProcessName);
System.Diagnostics.Process[] test_processNames = System.Diagnostics.Process.GetProcessesByName("myTest");
// if there is more than one process
if (testService_processNames.Length > 1 || test_processNames.Length >0)
{
eventLog1.WriteEntry("[myTest Info]: myTest is already running");
return;
}
else
{
//在App.config里定义了filepath和filename
System.Diagnostics.ProcessStartInfo Info = new System.Diagnostics.ProcessStartInfo();
Info.WorkingDirectory =System.Configuration.ConfigurationSettings.AppSettings.Get("filepath");//path of exe
Info.FileName =System.Configuration.ConfigurationSettings.AppSettings.Get("filename");//name of exe
//Info.Arguments = "";
// Info.CreateNoWindow=false;
// Info.Verb="open";
Info.WindowStyle=System.Diagnostics.ProcessWindowStyle.Normal;
// Info.UseShellExecute=true;
//声明一个程序类
System.Diagnostics.Process Proc ;
try
{
Proc=System.Diagnostics.Process.Start(Info);//启动外部程序myTest.exe
}
catch(System.ComponentModel.Win32Exception e)
{
eventLog1.WriteEntry("[myTest Info]: 系统找不到指定的程序文件。\r{0}"+ e.Message);
return;
}
// //打印出外部程序的开始执行时间
eventLog1.WriteEntry("外部程序的开始执行时间:{0}", Proc.StartTime);
//
// //等待3秒钟
// Proc.WaitForExit(3000);
//
// //如果这个外部程序没有结束运行则对其强行终止
// if(Proc.HasExited == false)
// {
// eventLog1.WriteEntry("由主程序强行终止外部程序的运行!");
// Proc.Kill();
// }
// else
// {
// eventLog1.WriteEntry("由外部程序正常退出!");
// }
// eventLog1.WriteEntry("外部程序的结束运行时间:{0}", Proc.ExitTime);
// eventLog1.WriteEntry("外部程序在结束运行时的返回值:{0}", Proc.ExitCode);
}
}
catch(System.Exception ex)
{
eventLog1.WriteEntry("[myTest Info]: Start error- " +ex.Message);
return;
}
}
========OnStop停止服务========
protected override void OnStop()
{
try
{
eventLog1.WriteEntry("[myTest Info]: Stop Begin!");
System.Diagnostics.Process[] Test_processNames = System.Diagnostics.Process.GetProcessesByName("myTest");
foreach(System.Diagnostics.Process processChild in Test_processNames)
{
eventLog1.WriteEntry("[PBX Info]: ProcessName= " +processChild.ProcessName);
processChild.Kill();
}
}
catch(System.Exception ex)
{
eventLog1.WriteEntry("[myTest Info]: Stop error- "+ex.Message);
return;
}
}
========写入txt日志文件========
public static void WriteLog(string strLog)
{
string strPath;
strPath="D:\\Test";
strPath+=@"\mylog.tx;
FileStream fs = new FileStream(strPath,FileMode.OpenOrCreate,FileAccess.Write);
StreamWriter m_streamWriter = new StreamWriter(fs);
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine(strLog);
m_streamWriter.Flush();
m_streamWriter.Close();
fs.Close();
}
========App.config========
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="filepath" value="D:\\myfile\\done" />
<add key="filename" value="myTest.exe" />
</appSettings>
</configuration>