Попытка установить службы Windows - что не так с этим кодом? - PullRequest
4 голосов
/ 10 ноября 2011

Я создаю проект службы Windows в VS2010, который содержит несколько служб.Я попытался собрать способ установить его без сложного установщика.Но, похоже, откат и не работает.

Вот Program.cs:

static class Program
{
    static void Main(string[] args)
    {
        bool install = false, uninstall = false, console = false;
        WindowsServiceInstaller inst = new WindowsServiceInstaller();

        if (args.Length > 0)
        {
            foreach (string arg in args)
            {
                switch (arg)
                {
                    case "-i":
                    case "-install":
                        install = true;
                        break;
                    case "-u":
                    case "-uninstall":
                        uninstall = true;
                        break;
                    case "-c":
                    case "-console":
                        console = true;
                        break;
                    default:
                        Console.Error.WriteLine("Argument not expected: " + arg);
                        break;
                }
            }
        }

        if (uninstall)
        {
            inst.InstallServices(false, args);
        }

        if (install)
        {
            inst.InstallServices(true, args);
        }

        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            // scans Email table for outbound email jobs; uses multiple threads to lock and work on data in Email table
              new EmailLogScanner()

            // generates email digest of document status on secheduled basis; single thread
            , new EmailStatusDigester() 

            // keeps Fax table and third-party fax service accounts synchronized; uses a fixed nb of threads, one thread syncs one account at a time
            , new FaxSynchronizer()     
        };

        if (console)
        {

            foreach (IDebuggableService srv in ServicesToRun)
            {
                string[] strs = new string[] { String.Empty };
                srv.DebugStart(strs);
            }

            Console.WriteLine("Press any key to terminate...");
            Console.ReadKey();

            foreach (IDebuggableService srv in ServicesToRun)
            {
                srv.DebugStop();
            }

            Console.WriteLine("Service has exited.");
        }
        else
        {
            ServiceBase.Run(ServicesToRun);
        }
    }
}

Вот WindowsServiceInstaller.cs:

[RunInstaller(true)]
public class WindowsServiceInstaller : Installer 
{
    public WindowsServiceInstaller()
    {
        ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller();
        serviceProcessInstaller.Account = ServiceAccount.NetworkService;
        serviceProcessInstaller.Username = null;
        serviceProcessInstaller.Password = null;
        Installers.Add(serviceProcessInstaller);

        ServiceInstaller emailLogScannerInstaller = new ServiceInstaller();
        emailLogScannerInstaller.DisplayName = "Email Scanner";
        emailLogScannerInstaller.StartType = ServiceStartMode.Automatic;
        emailLogScannerInstaller.ServiceName = "EmailLogScanner"; // must match the ServiceBase ServiceName property
        emailLogScannerInstaller.Description = "Scan for and sends out pending emails in stack.";
        Installers.Add(emailLogScannerInstaller);

        ServiceInstaller emailStatusDigesterInstaller = new ServiceInstaller();
        emailStatusDigesterInstaller.DisplayName = "Status Digester";
        emailStatusDigesterInstaller.StartType = ServiceStartMode.Automatic;
        emailStatusDigesterInstaller.ServiceName = "EmailDigester";
        emailStatusDigesterInstaller.Description = "Prepares document status email digests.";
        Installers.Add(emailStatusDigesterInstaller);

        ServiceInstaller faxSynchronizerInstaller = new ServiceInstaller();
        faxSynchronizerInstaller.DisplayName = "Fax Synchronizer";
        faxSynchronizerInstaller.StartType = ServiceStartMode.Automatic;
        faxSynchronizerInstaller.ServiceName = "FaxSynchronizer";
        faxSynchronizerInstaller.Description = "Synchronizes database with external fax service(s).";
        Installers.Add(faxSynchronizerInstaller);           

    }

    public void InstallServices(bool doInstall, string[] args)
    {
        try
        {
            using (AssemblyInstaller aInstaller = new AssemblyInstaller(typeof(Program).Assembly, args))
            {
                IDictionary state = new Hashtable();
                aInstaller.UseNewContext = true;
                try
                {
                    if (doInstall)
                    {
                        aInstaller.Install(state);
                        aInstaller.Commit(state);
                    }
                    else
                    {
                        aInstaller.Uninstall(state);
                    }
                }
                catch
                {
                    try
                    {
                        aInstaller.Rollback(state);
                    }
                    catch { }
                    throw;
                }
            }
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex.Message);
        }
    }

}

Зарегистрированный вывод (когда язапустите daemon.exe -i в командной строке, как администратор) показывает текст ниже.Кроме того, я получаю диалоговое окно «Не удается запустить службу из командной строки»:

Installing assembly 'C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe'.
Affected parameters are:
   i = 
   assemblypath = C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe
   logfile = C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.InstallLog
Installing service EmailLogScanner...
Service EmailLogScanner has been successfully installed.
Creating EventLog source EmailLogScanner in log Application...
See the contents of the log file for the C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe assembly's progress.
The file is located at C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.InstallLog.
Rolling back assembly 'C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe'.
Affected parameters are:
   logtoconsole = 
   i = 
   assemblypath = C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe
   logfile = C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.InstallLog
Restoring event log to previous state for source EmailLogScanner.
Service EmailLogScanner is being removed from the system...
Service EmailLogScanner was successfully removed from the system.

ОБНОВЛЕНИЕ: Когда я закомментирую блок try ... catch вокруг строки 'aInstaller.Install (state)',Я получаю немного другой вывод:

Installing assembly 'C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe'.
Affected parameters are:
   i =
   assemblypath = C:\Users\xxx\Documents\~Business\Projects\Da
emon\bin\Release\Daemon.exe
   logfile = C:\Users\xxx\Documents\~Business\Projects\Daemon\
bin\Release\Daemon.InstallLog
Installing service EmailLogScanner...
Creating EventLog source EmailLogScanner in log Application...
Source EmailLogScanner already exists on the local computer.

Это потому, что у меня уже настроены источники журнала событий?Если да, то как мне пропустить этот шаг в AssemblyInstaller?Если нет, то как?:)

1 Ответ

0 голосов
/ 10 ноября 2011

Вы должны поставить это

if (EventLog.SourceExists("YourEventSourceName"))
    EventLog.DeleteEventSource("YourEventSourceName");

когда начинается установка службы.

...