今天试着用C#编写Windows service. 有几个要求,
第一,可通过参数注册服务
第二,也可通过参数取消注册
第三,可以传递参数给服务
第四,注册成功后,可以弹出窗口进行具体配置
其中第三点,在这里做个备注,传递参数有两种,一种是在Main函数接收参数,一种是在OnStart接收参数
在Main中接收的参数在注册之后,必须要到注册表中进行手工设定,而且这里设定参数不仅Main中可以通过Environment.GetCommandLineArgs()
获得,OnStart函数也可以通过这种方式获得。
OnStart中的参数,只能透过ServiceController.Start()传递,或手工在服务启动窗口中输入,注意,在启动窗口中输入的参数只对本次启动有效,windows是不会记住上次的参数的。若想要在OS启动服务时就带固定的参数,只能通过注册表的方式进行修改。
Parameters you send using ServiceController.Start() method are available to you as parameters to the OnStart() method. If I'm not mistaken (It's been a while since I needed to do this).
The OnStart method's signature is:
OnStart(string[] args)
However, if you need the parameters to be sent to the service each time the service is started (automatically) on boot, then you should look at the MSDN documentation on this. Specifically
Process initialization arguments for the service in the OnStart method, not in the Main method. The arguments in the args parameter array can be set manually in the properties window for the service in the Services console. The arguments entered in the console are not saved; they are passed to the service on a one-time basis when the service is started from the control panel. Arguments that must be present when the service is automatically started can be placed in the ImagePath string value for the service's registry key (HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServices). You can obtain the arguments from the registry using the GetCommandLineArgs method, for example: string[] imagePathArgs = Environment.GetCommandLineArgs();.
http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.onstart.aspx
以下代码可以在安装过程中为注册表中写入参数
using System;
using System.ServiceProcess;
using System.Collections;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Web.Services;
using System.Diagnostics;
using System.IO;
using System.Configuration.Install;
/*
* This is the ProjectInstaller class used to install the project
*/
[RunInstallerAttribute(true)]
publicclass ProjectInstaller: Installer
{
privatestatic Boolean initialized = false;
privatestatic Boolean installing = false;
private ServiceInstaller serviceInstaller;
private ServiceProcessInstaller processInstaller;
private String command;
public ProjectInstaller()
{
BeforeInstall += new InstallEventHandler(BeforeInstallEventHandler);
BeforeUninstall += new InstallEventHandler(BeforeUninstallEventHandler);
}
privatevoid initialize()
{
String username = null;
String password = null;
Console.WriteLine("
---------------------------------------");
Console.WriteLine("Please Enter the name of the Service:
");
String serviceName = Console.ReadLine();
Console.WriteLine("
Please Enter the Service's user account:
");
username = Console.ReadLine();
Console.WriteLine("
Please Enter the user account password
");
password = Console.ReadLine();
if (installing)
{
Console.WriteLine("
Please Enter the command you wish to execute
");
this.command = Console.ReadLine();
}
Console.WriteLine("
Thanks Dude!
");
Console.WriteLine("---------------------------------------");
// Instantiate installers for process and services.
processInstaller = new ServiceProcessInstaller();
serviceInstaller = new ServiceInstaller();
// The services run under a User Account
processInstaller.Account = ServiceAccount.User;
processInstaller.Username = username;
processInstaller.Password = password;
// The services are started manually.
serviceInstaller.StartType = ServiceStartMode.Manual;
// ServiceName must equal those on ServiceBase derived classes.
serviceInstaller.ServiceName = serviceName;
// Add installers to collection. Order is not important.
Installers.Add(serviceInstaller);
Installers.Add(processInstaller);
initialized = true;
}
/*
* Installs the Service but adds a parameters entry
* into the registry under the Service.
*/
publicoverridevoid Install(IDictionary stateServer)
{
Microsoft.Win32.RegistryKey system,
currentControlSet,
services,
service,
config;
try
{
//Let the project installer do its job
base.Install(stateServer);
//Open the HKEY_LOCAL_MACHINESYSTEM 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.serviceInstaller.ServiceName, true);
//Add your service's description as a REG_SZ value named "Description"
service.SetValue("Description", this.serviceInstaller.ServiceName + " Description");
//(Optional) Add some custom information your service will use...
config = service.CreateSubKey("Parameters");
config.SetValue("Arguments", command);
Console.WriteLine(service.GetValue("ImagePath"));
string path = service.GetValue("ImagePath") + " " +
this.serviceInstaller.ServiceName;
service.SetValue("ImagePath", path);
}
catch(Exception e)
{
Console.WriteLine("An exception was thrown during service installation:
" + e.ToString());
}
}
/*
* UnInstalls the Service and removes the parameters entry
* from the registry under the Service.
*/
publicoverridevoid Uninstall(IDictionary stateServer)
{
Microsoft.Win32.RegistryKey system,
currentControlSet,
services,
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.serviceInstaller.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:
" + e.ToString());
}
finally
{
//Let the project installer do its job
base.Uninstall(stateServer);
}
}
privatevoid BeforeInstallEventHandler(object sender, InstallEventArgs e)
{
Console.WriteLine("
Before Install");
installing = true;
if (!initialized)
{
initialize();
}
}
privatevoid BeforeUninstallEventHandler(object sender, InstallEventArgs e)
{
Console.WriteLine("
Before UnInstall");
installing = false;
if (!initialized)
{
initialize();
}
}
}
/*
* The SISService class used to run executables
*/
class DynService : System.ServiceProcess.ServiceBase
{
private Process process;
public String processName;
public DynService()
{
this.ServiceName = "BOB";
}
publicstaticvoid Main(string [] args)
{
SISService service = new DynService();
if (args.Length != 0)
{
service.ServiceName = args[0];
}
ServiceBase.Run(service);
}
protectedoverridevoid OnStart(string[] args)
{
process = new Process();
process.StartInfo.FileName = ReadArguments();
process.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
process.Start();
}
///<summary>
/// Stop this service.
///</summary>
protectedoverridevoid OnStop()
{
process.Kill();
}
protectedoverridevoid OnShutdown()
{
process.Kill();
}
protectedoverridevoid OnCustomCommand(int command)
{
if (command == 144)
{
}
}
protected String ReadArguments()
{
Microsoft.Win32.RegistryKey system,
currentControlSet,
services,
service,
param;
//Open the HKEY_LOCAL_MACHINESYSTEM 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.ServiceName, false);
param = service.OpenSubKey("Parameters", false);
String args = (String) param.GetValue("Arguments");
return args;
}
}
下列代码设定服务允许与桌面交互
private void serviceProcessInstaller1_Committed(object sender, InstallEventArgs e)
{
try
{
ConnectionOptions myConOptions = new ConnectionOptions();
myConOptions.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope mgmtScope = new System.Management.ManagementScope(@"rootCIMV2", myConOptions);
mgmtScope.Connect();
ManagementObject wmiService = new ManagementObject("Win32_Service.Name='" + serviceInstaller1.ServiceName + "'");
ManagementBaseObject InParam = wmiService.GetMethodParameters("Change");
InParam["DesktopInteract"] = true;
ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null);
}
catch (Exception err)
{
Common.wLog(err.ToString());
}
}