2012-08-31 1256 views
76

通常、このエラーが発生します: (ローカルコンピュータの「サービス名」サービスが開始され、停止しました。私のコードに何か問題がある場合(存在しないドライブパスなど)、Windowsサービスは起動しません。ローカルコンピュータ上のWindowsサービスが起動して停止したエラー

私は、フォルダ/ファイルをサイズ制限に達した場所にバックアップするWindowsサービスを用意しています。詳細はすべて、Windowsサービスが開始時に読み取るXML設定によって提供されます。私は、私のWindowsサービスが起動していることを正確に行うボタンを持つ別個のWindowsフォームを持っています。私は私のWindowsサービスに入れる前にコードをデバッグするために私のWindowsフォームを使用します。

私のウィンドウズフォームを起動するとき。それはそれがすると思われることをします。 WindowsサービスのOnStart()メソッドにコードを挿入すると、エラーが表示されました。ここで

は私のコードです:私は、Windowsサービスが起動しませ続けるかわからない

protected override void OnStart(string[] args) 
{ 

    private static string backupConfig = @"D:\LogBackupConfig\backupconfig.xml"; 
    private static string serviceStat = @"D:\LogBackupConfig\Status.txt"; 
    private static string fileFolderStat = @"D:\LogBackupConfig\FileFolderStat.txt"; 

    protected override void OnStart(string[] args) 
    { 
     if (File.Exists(backupConfig)) 
     { 
      FileSystemWatcher watcher = new FileSystemWatcher(); 
      XmlTextReader reader = new XmlTextReader(backupConfig); 

      XmlNodeType type; 
      List<string> listFile = new List<string>(); 
      string fileWatch = ""; 

      //this loop is for reading XML elements and assigning to variables 
      while (reader.Read()) 
      { 
       type = reader.NodeType; 
       if (type == XmlNodeType.Element) 
       { 
        if (reader.Name == "File") 
        { 
         reader.Read(); 
         fileWatch = reader.Value; 
        } 
        else if (reader.Name == "Folder") 
        { 
         reader.Read(); 
         fileWatch = reader.Value; 
        } 
       } 
      } 
      reader.Close(); 

      watcher.Path = fileWatch; 
      watcher.Filter = "*.*"; 

      //this loop reads whether the service will watch a file/folder 
      XmlTextReader reader1 = new XmlTextReader(backupConfig); 
      while (reader1.Read()) 
      { 
       type = reader1.NodeType; 
       if (type == XmlNodeType.Element) 
       { 
        if (reader1.Name == "File") 
        { 
         watcher.IncludeSubdirectories = false; 
         watcher.Changed += new FileSystemEventHandler(OnChangedFile); 
        } 
        else if (reader1.Name == "Folder") 
        { 
         watcher.IncludeSubdirectories = true; 
         watcher.Changed += new FileSystemEventHandler(OnChangedFolder); 
        } 
       } 
      } 
      reader1.Close(); 

      watcher.EnableRaisingEvents = true; 

     } 
     else 
     { 
      StreamWriter sw = new StreamWriter(serviceStat, true); 
      sw.WriteLine("File not found. Please start the Log Backup UI first."); 
      sw.Close(); 
     } 
    } 

、Windowsフォームシミュレータがうまく働きました。問題であると想定されるのは?

更新日: 私は、フォルダディレクトリ(ファイルを含む)のみを使用していることに気付きましたが、Windowsサービスは機能しません。 fileWatch変数を特定のファイル(そのディレクトリを含む)に置き換えると、Windowsサービスが開始されました。私がそれをフォルダの場所に戻したとき、それはうまくいかなかった。私が考えているのは、ファイルウォッチャーではフォルダの場所が機能しないということです。

フォルダの場所を監視する新しいWindowsサービスを作成しようとしましたが、正常に機能しました。ただし、元のWindowsサービスで同じ場所を試しても機能しませんでした。私は心配していました。私は新しいWindowsサービスを作成し、新しいコード/関数を配置するたびにインストーラをビルドする必要があるようです。この方法で、どこでエラーが発生するのかを追跡できます。

答えて

156

サービスがそのように開始され停止する場合は、コードで未処理の例外がスローされていることを意味します。これはデバッグするのがかなり難しいですが、いくつかのオプションがあります。

  1. Windows イベントビューアを参照してください。通常は、コンピュータ/サーバーマネージャーにアクセスして、イベントビューア - >Windowsログ - >アプリケーションをクリックして、これを行うことができます。ここで例外を投げたものを見ることができますが、スタックトレースは得られません。
  2. プログラムロジックをライブラリクラスプロジェクトに抽出します。コンソールアプリケーション(デバッグ用)とWindowsサービスの2種類のプログラムを作成します。 (初期の努力は少しですが、長期的には心配はありません)
  3. さらに詳しい情報を得るには、try/catchブロックとログをアプリに追加してください。
+5

ありがとうございました! "System.ArgumentException:パスが正当な形式ではありません。System.IO.Path.NormalizePath(String path、Boolean fullCheck、Int32 maxPathLength)の システム内の のシステムでエラーが発生しました。 .IO.Path.GetFullPathInternal(String path) at System.IO.Path。System.ServiceProcess.ServiceBaseでGetFullPath(文字列のパス)System.IO.FileSystemWatcher.StartRaisingEventsで ()System.IO.FileSystemWatcher.set_EnableRaisingEvents(ブール値)で LogBackupWinSvc.Service1.OnStart(文字列[]引数)で 。 ServiceQueuedMainCallback(オブジェクト状態) " – Blackator

+3

Windowsイベントビューアは完全なスタックトレースを表示し、非常に有用なツールです。 –

0

ファイルをコピーするためにタイマーとティックイベントを使用します。

サービスを開始するときに時間を開始し、その時間を指定します。

サービスは継続して実行され、ファイルはontickにコピーされます。

希望します。

0

初期化をユニットテストすることができますが、これはOnStartメソッドにあるため、これは不可能に近いものです。初期化コードを別のクラスに移動してテストするか、少なくともフォームテスターで再利用することをお勧めします。

第2に、いくつかのログを追加し(Log4Netなどを使用)、詳細なログを追加してランタイムエラーの詳細を確認します。ランタイムエラーの例は、AccessViolationなどです。特に、サービスが設定ファイルにアクセスするための十分な特権なしで実行されている場合。

28

これが参考になりますが、サービスをデバッグするためには、常にのOnStartメソッドで次のように使用することができわからない:あなたがプロセスにあなたのVisual Studioを添付し、より優れたデバッグ能力を持っている可能性がより

protected override void OnStart(string[] args) 
{ 
    System.Diagnostics.Debugger.Launch(); 
    ... 
} 

。 -drive(彼らはユーザー固有のものです):

+0

これはデバッグのための素晴らしいソリューションです –

+0

これは、少なくとも私にとっては最良のソリューションです。私にとって、JITデバッガのUAC確認ダイアログがポップアップして、デバッガとしてVS 2015を選択させてください。 – Smitty

0

、これは参考になりました 幸運を願ってサービスを実行しているアカウントは、Dがマッピングされていない可能性があります。ディレクトリを共有して、backupConfigで完全なUNCパスを使用してください。

FileSystemWatcherwatcherはローカル変数であり、OnStartメソッドが実行されたときに範囲外です。おそらく、それをインスタンス変数またはクラス変数として必要とします。

8

私はコンソールに既存のWindowsサービスを変換することは非常に便利な発見しましたを次のように変更するだけです。この変更により、ビジュアルスタジオでデバッグするか、実行ファイルを正常に実行することでプログラムを実行できます。しかし、それはまた、Windowsサービスとして動作します。 I also made a blog post about it

Program.csの

class Program 
{ 
    static void Main() 
    { 
     var program = new YOUR_PROGRAM(); 
     if (Environment.UserInteractive) 
     { 
      program.Start(); 
     } 
     else 
     { 
      ServiceBase.Run(new ServiceBase[] 
      { 
       program 
      }); 
     } 
    } 
} 

YOUR_PROGRAM.cs

[RunInstallerAttribute(true)] 
public class YOUR_PROGRAM : ServiceBase 
{ 
    public YOUR_PROGRAM() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnStart(string[] args) 
    { 
     Start(); 
    } 

    protected override void OnStop() 
    { 
     //Stop Logic Here 
    } 

    public void Start() 
    { 
     //Start Logic here 
    } 
} 
+2

ちょうど参考までに、ブログは機能しません。 –

0

私は同じ問題に出くわしました。私のサービスはXMLSをアップロード/受信し、エラーをイベントログに書き出します。

私がイベントログに行ったとき、私はそれをフィルタリングしようとしました。イベントログが破損していることがわかります。

イベントログをすべてクリアしてOKです。

1

EventLog.Logは「アプリケーション」に設定する必要があります

+0

これは実際に問題の解決策でした。私 – Savage

関連する問題