3

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);
        }
    }
}
4

2 に答える 2

3

サービスをどこにインストールしましたか? このエラーは、ローカル サービス アカウントがサービスの場所にアクセスできないことを示しているようです。そのため、サービス マネージャーは、サービスを開始するどころか、実行可能ファイルを読み込んで実行することさえできません。

サービスを開発/デバッグするときに、開発者がこれを行うのをよく見てきました。開発フォルダーの 1 つからサービスをインストールしますが、別のアカウントで実行するように設定します。ただし、デフォルトでは、ユーザー、システム、および管理者グループのみがユーザーのフォルダーにアクセスできるため、サービスはアクセス拒否エラーで失敗します。

于 2012-10-17T01:58:07.777 に答える
0

使用しているオペレーティング システムは何ですか?

マイクロソフトによると

値 LocalService および NetworkService は、Windows XP および Windows Server 2003 ファミリでのみ使用できます。

このコメントを最初にここで読んだとき、これらのオペレーティング システムが最新バージョンであったときに書かれたものであり、以前のオペレーティング システムを除外するために書かれたものだと思いましたが、このコメントは最新のドキュメントにまだ存在しています。

于 2012-10-16T11:10:00.357 に答える