Да, это полностью возможно (т.е. Я делаю точно это); просто необходимо сослаться на право dll (System.ServiceProcess.dll) и добавить класс установщика...
[RunInstaller(true)]
public sealed class MyServiceInstallerProcess : ServiceProcessInstaller
{
public MyServiceInstallerProcess()
{
this.Account = ServiceAccount.NetworkService;
}
}
[RunInstaller(true)]
public sealed class MyServiceInstaller : ServiceInstaller
{
public MyServiceInstaller()
{
this.Description = "Service Description";
this.DisplayName = "Service Name";
this.ServiceName = "ServiceName";
this.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
}
}
static void Install(bool undo, string[] args)
{
try
{
Console.WriteLine(undo ? "uninstalling" : "installing");
using (AssemblyInstaller inst = new AssemblyInstaller(typeof(Program).Assembly, args))
{
IDictionary state = new Hashtable();
inst.UseNewContext = true;
try
{
if (undo)
{
inst.Uninstall(state);
}
else
{
inst.Install(state);
inst.Commit(state);
}
}
catch
{
try
{
inst.Rollback(state);
}
catch { }
throw;
}
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
}
Вот класс, который я использую при записи сервисов. У меня обычно есть интерактивный экран, который подходит, когда сервис не называют. Оттуда я использую класс по мере необходимости. Это допускает несколько именованных экземпляров на той же машине - следовательно Демонстрационный Вызов поля
InstanceID
IntegratedServiceInstaller Inst = new IntegratedServiceInstaller();
Inst.Install("MySvc", "My Sample Service", "Service that executes something",
_InstanceID,
// System.ServiceProcess.ServiceAccount.LocalService, // this is more secure, but only available in XP and above and WS-2003 and above
System.ServiceProcess.ServiceAccount.LocalSystem, // this is required for WS-2000
System.ServiceProcess.ServiceStartMode.Automatic);
if (controller == null)
{
controller = new System.ServiceProcess.ServiceController(String.Format("MySvc_{0}", _InstanceID), ".");
}
if (controller.Status == System.ServiceProcess.ServiceControllerStatus.Running)
{
Start_Stop.Text = "Stop Service";
Start_Stop_Debugging.Enabled = false;
}
else
{
Start_Stop.Text = "Start Service";
Start_Stop_Debugging.Enabled = true;
}
сам класс
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Microsoft.Win32;
namespace MySvc
{
class IntegratedServiceInstaller
{
public void Install(String ServiceName, String DisplayName, String Description,
String InstanceID,
System.ServiceProcess.ServiceAccount Account,
System.ServiceProcess.ServiceStartMode StartMode)
{
//http://www.theblacksparrow.com/
System.ServiceProcess.ServiceProcessInstaller ProcessInstaller = new System.ServiceProcess.ServiceProcessInstaller();
ProcessInstaller.Account = Account;
System.ServiceProcess.ServiceInstaller SINST = new System.ServiceProcess.ServiceInstaller();
System.Configuration.Install.InstallContext Context = new System.Configuration.Install.InstallContext();
string processPath = Process.GetCurrentProcess().MainModule.FileName;
if (processPath != null && processPath.Length > 0)
{
System.IO.FileInfo fi = new System.IO.FileInfo(processPath);
String path = String.Format("/assemblypath={0}", fi.FullName);
String[] cmdline = { path };
Context = new System.Configuration.Install.InstallContext("", cmdline);
}
SINST.Context = Context;
SINST.DisplayName = String.Format("{0} - {1}", DisplayName, InstanceID);
SINST.Description = String.Format("{0} - {1}", Description, InstanceID);
SINST.ServiceName = String.Format("{0}_{1}", ServiceName, InstanceID);
SINST.StartType = StartMode;
SINST.Parent = ProcessInstaller;
// http://bytes.com/forum/thread527221.html
SINST.ServicesDependedOn = new String[] { "Spooler", "Netlogon", "Netman" };
System.Collections.Specialized.ListDictionary state = new System.Collections.Specialized.ListDictionary();
SINST.Install(state);
// http://www.dotnet247.com/247reference/msgs/43/219565.aspx
using (RegistryKey oKey = Registry.LocalMachine.OpenSubKey(String.Format(@"SYSTEM\CurrentControlSet\Services\{0}_{1}", ServiceName, InstanceID), true))
{
try
{
Object sValue = oKey.GetValue("ImagePath");
oKey.SetValue("ImagePath", sValue);
}
catch (Exception Ex)
{
System.Windows.Forms.MessageBox.Show(Ex.Message);
}
}
}
public void Uninstall(String ServiceName, String InstanceID)
{
//http://www.theblacksparrow.com/
System.ServiceProcess.ServiceInstaller SINST = new System.ServiceProcess.ServiceInstaller();
System.Configuration.Install.InstallContext Context = new System.Configuration.Install.InstallContext("c:\\install.log", null);
SINST.Context = Context;
SINST.ServiceName = String.Format("{0}_{1}", ServiceName, InstanceID);
SINST.Uninstall(null);
}
}
}
Обратите внимание на метод InstallHelper класса ManagedInstaller . Вы можете установить службу, используя:
string[] args;
ManagedInstallerClass.InstallHelper(args);
Это именно то, что делает InstallUtil. Аргументы те же, что и для InstallUtil.
Преимущества этого метода заключаются в том, что он не вызывает беспорядка в реестре и использует тот же механизм, что и InstallUtil.
Вы всегда можете вернуться к старым добрым вызовам WinAPI, хотя объем работы нетривиален. Не требуется, чтобы службы .NET устанавливались с помощью механизма, поддерживающего .NET.
Для установки:
OpenSCManager
. CreateService
], чтобы зарегистрировать службу. ChangeServiceConfig2
, чтобы задать описание. CloseServiceHandle
. Для удаления:
OpenSCManager
. OpenService
. DeleteService
для дескриптора, возвращенного OpenService
. CloseServiceHandle
. Основная причина, по которой я предпочитаю это использование ServiceInstaller
/ ServiceProcessInstaller
, заключается в том, что вы можете зарегистрируйте службу с вашими собственными аргументами командной строки. Например, вы можете зарегистрировать его как "MyApp.exe -service"
, а затем, если пользователь запустит ваше приложение без каких-либо аргументов, вы можете предложить ему пользовательский интерфейс для установки / удаления службы.
Запуск Reflector на ServiceInstaller
может заполнить детали, отсутствующие в этом кратком объяснении.
PS Ясно, что это не будет иметь «такого же эффекта, как вызов: InstallUtil MyService.exe» - в частности, вы не будете можно удалить с помощью InstallUtil. Но похоже, что, возможно, это было не так.