2011-11-10 7 views
4

複数のサービスを含むVS2010でWindowsサービスプロジェクトを作成します。私は、複雑なインストーラを使わずにインストールする方法をまとめました。しかし、それはロールバックして動作していないようです。ここでWindowsサービスをインストールしようとしています - このコードでは何が間違っていますか?

は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. 

UPDATE:また、私は、「コマンドラインからサービスを開始することはできません」ダイアログを取得し、私は「aInstaller.Install(状態)」行の周りのtry ... catchブロックをコメントアウトすると、私が手少し異なる出力:

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でその手順をスキップするにはどうすればよいですか?そうでなければ、そう? :)

+0

「ファイルはC:¥Users¥xxx¥Documents¥〜Business¥Projects¥Daemon¥bin¥Release¥Daemon.InstallLog」にありますか? –

+0

実際、上記の最後のブロックはInstallLogファイルに記録されているものです。 – alphadogg

+1

ああ、それでは問題じゃない? "Source EmailLogScannerはローカルコンピュータに既に存在しています。"おそらく、インストールするたびにイベントソースを作成するように見えますが、アンインストールはイベントソースを削除していない可能性があります。それ以来、それは既に存在するので、それを作成することに失敗しています。 –

答えて

0

あなたは入れなければならない。この

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

サービスのインストールが開始されます。

+0

実際、私の問題はこれの変種でした。私は3つの異なるサービスを持っています。各サービスでは、ServiceBaseコンストラクタでEventSourceを作成したコードがあります。 ServiceInstallerがEventSourceを作成しようとする前にチェックしていないようで、競合が発生しているようです。私は、サービスがコンソール経由で実行されていた場合にソースを作成できるように違反コードを別のメソッドに移動しました。 – alphadogg

+0

あなたが実際に答えたので、私はあなたにポイントを与えました。 ;) – alphadogg

関連する問題