ServiceProcessInstaller を使用して C# サービスをインストールします (現在 Windows 7 にあり、XP と 2003以降にしか存在しないと読んだことがありますが、処理する必要があるのはそれだけです)。私のサービスは「ローカル システム」で実行できますが、「ローカル サービス」や「ネットワーク サービス」では実行できません。サービスが基本的に空であっても (以下のコードを参照)、
Windows はローカル コンピューターで [サービス名] サービスを開始できませんでした。エラー 5: アクセスが拒否されました。
これが私のほとんど空のサービスです: 編集 「ローカルサービス」に必要なアクセス権を与えるようにコードを更新しました。
// Needs System.Configuration.Install.dll and System.ServiceProcess.dll
using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using System.Reflection;
using System.ServiceProcess;
namespace ServiceTest
{
static class Constants
{
public const string LocalServiceAcctName = @"NT AUTHORITY\LOCAL SERVICE";
public const string ServiceName = "MySvc";
}
class Program
{
/// <summary>
/// Main entry point.
/// </summary>
/// <param name="args">
/// If the 1st argument is "i", it will simply install the service.
/// If it's something else, it will run as a Console application.
/// If it's empty, it will run as a service.
/// </param>
static void Main(string[] args)
{
if (args != null && args.Length != 0 && args[0] == "i")
{
bool result = InstallService(Assembly.GetExecutingAssembly().Location, Constants.ServiceName);
Console.WriteLine(result ? "INSTALLED" : "ERROR INSTALLING");
Console.ReadLine();
}
else
{
var host = new Host();
bool runAsSvc = args == null || args.Length == 0;
host.Launch(runAsSvc);
}
}
static bool InstallService(string exeFullPath, string serviceName)
{
AssemblyInstaller installer = new AssemblyInstaller(exeFullPath, null);
if (ServiceController.GetServices().Any(svcCtlr => svcCtlr.ServiceName == serviceName))
installer.Uninstall(null);
Hashtable dico = new Hashtable();
installer.Install(dico);
installer.Commit(dico);
// Gives "Local Service" the necessary rights on the folder and subfolders and files.
DirectoryInfo dirInfo = new DirectoryInfo(Path.GetDirectoryName(exeFullPath));
DirectorySecurity dirSec = dirInfo.GetAccessControl(AccessControlSections.Access);
FileSystemRights rights = FileSystemRights.Modify;
AccessControlType accessType = AccessControlType.Allow;
dirSec.AddAccessRule(new FileSystemAccessRule(Constants.LocalServiceAcctName, rights, InheritanceFlags.ObjectInherit, PropagationFlags.InheritOnly, accessType));
dirSec.AddAccessRule(new FileSystemAccessRule(Constants.LocalServiceAcctName, rights, InheritanceFlags.ContainerInherit, PropagationFlags.InheritOnly, accessType));
dirSec.AddAccessRule(new FileSystemAccessRule(Constants.LocalServiceAcctName, rights, accessType));
dirInfo.SetAccessControl(dirSec);
return true;
}
}
class Host
{
internal void Launch(bool runAsSvc)
{
if (runAsSvc)
RuntimeService.CreateAndRun(this);
else
{
OnStart();
Console.WriteLine("Component started as a Console app.");
Console.WriteLine("We work a lot...and then we're done.");
OnStop();
Console.WriteLine("Press enter to stop.");
Console.ReadLine();
}
}
internal void OnStart() { Console.WriteLine("We're starting!"); }
internal void OnStop() { Console.WriteLine("We're stopping..."); }
}
class RuntimeService : ServiceBase
{
Host _host;
public RuntimeService(Host host) { _host = host; }
protected override void OnStart(string[] args) { _host.OnStart(); }
protected override void OnStop() { _host.OnStop(); }
internal static void CreateAndRun(Host host) { ServiceBase.Run(new RuntimeService(host)); }
}
/// <summary>
/// Class used to install the service.
/// </summary>
[RunInstaller(true)]
public class RuntimeInstaller : Installer
{
public RuntimeInstaller()
{
var processInstaller = new ServiceProcessInstaller();
processInstaller.Account = ServiceAccount.LocalService; // ServiceAccount.LocalSystem;
var serviceInstaller = new ServiceInstaller();
serviceInstaller.StartType = ServiceStartMode.Automatic;
serviceInstaller.ServiceName = Constants.ServiceName;
Installers.Add(serviceInstaller);
Installers.Add(processInstaller);
}
}
}