WindowsサービスプログラムでXMLファイルを設定情報として使用する方法

WindowsサービスプログラムでXMLを設定ファイルとして使用する方法を実装してみた。

####**1.Windowsサービスプログラムを作成**
![WinSvc1.png](https://qiita-image-store.s3.amazonaws.com/0/184967/5e46514f-1dd5-9ccf-eff5-bdcdd4aa85f1.png)

* ここではWindowsサービスの設定方法の詳細は割愛するが、インストーラーを追加する際、「Account」は「LocalSystem」にする(デフォルトは「User」)。


####**2.設定用XMLファイルを作成**
![無題4.png](https://qiita-image-store.s3.amazonaws.com/0/184967/f884cdd3-747d-d3a0-c04c-4662ad711cad.png)

* プロパティ→ビルドアクションを「**埋め込みリソース**」にする。ここが重要で、Windowsサービスプログラムだとこの設定でないとxmlファイルを使用することができない。


####**3.サービス処理の実装**
**3.1.デシリアライズ用のメソッド**

```c#
using System.IO;
using System.Runtime.Serialization;
using System.Xml;

namespace WinServiceAppSample1 {
	public class LoadXML {
		public static T Load<T>(Stream stream) where T : new() {

			T result = default(T);

			var serializer = new DataContractSerializer(typeof(T));

			using(var reader = XmlReader.Create(stream)) {
				result = (T)serializer.ReadObject(reader);
			}

			return result;
		}
	}
}

```

**3.2.デシリアライズ対象オブジェクトのためのクラス**

```c#
using System.Runtime.Serialization;

namespace WinServiceAppSample1 {

	[DataContract(Name = "root")]
	public class ObjSetting {

		[DataMember(Name = "settings")]
		public Settings settings {
			get;private set;
		}
	}

	[DataContract(Name = "settings")]
	public class Settings {
		[DataMember(Name = "save-dir")]
		public string SaveDir {
			get; private set;
		}

		[DataMember(Name = "save-log")]
		public string SaveLog {
			get; private set;
		}
	}
}


```

* ここまでは、普通のDataContractSerializerを使用したxmlのデシリアライズと同様の方法だが、埋め込みリソースにしているxmlファイルをStreamクラスに変換させる必要がある。これは「Assembly」クラスを使用して実装する。

**3.3.埋め込みリソースをStreamクラスに変換してデシリアライズ**

```c#

using System.Reflection;
using System.IO;

namespace WinServiceAppSample1 {
	public class Execute {
		public void LoadXml() {
			//【重要】xmlファイル名を指定する場合は「プロジェクト名.File1.xml」という形式にする必要がある
			var xmlfile = "WinServiceAppSample1.XMLSettingFile.xml";

			var assembly = Assembly.GetExecutingAssembly();
			var assxml = assembly.GetManifestResourceStream(xmlfile);

			var objsetting = LoadXML.Load<ObjSetting>(assxml);

			using(var sw = new StreamWriter(Path.Combine(objsetting.settings.SaveDir, objsetting.settings.SaveLog),true)) {
				sw.WriteLine(System.DateTime.Now);
			}
		}
	}
}

```

* コードにも記載しているが、xmlファイル名は「プロジェクト名.File1.xml」という形式にする必要がある。別フォルダにある場合は、「プロジェクト名.HOGE_DIR.File1.xml」となる。

単体テスト

```c#

using Microsoft.VisualStudio.TestTools.UnitTesting;
using WinServiceAppSample1;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace WinServiceAppSample1.Tests {
	[TestClass()]
	public class ExecuteTests {
		[TestMethod()]
		public void LoadXmlTest() {

			//Arrange
			var filename = @"C:\temp\hoge.log";
			File.Delete(filename);

			//Act
			var exec = new Execute();
			exec.LoadXml();

			//Asset
			Assert.AreEqual(File.Exists(filename), true);
		}
	}
}

```

**3.5.OnStartの実装**
Windowsサービスの実装方法の詳細は割愛する。以下コードのみを記載。

```c#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace WinServiceAppSample1 {
	public partial class SvcAppSample1 : ServiceBase {

		private Timer timer;
		public SvcAppSample1() {
			InitializeComponent();
		}

		protected override void OnStart(string[] args) {
			timer = new Timer(10000);
			timer.Elapsed += (s, e) => {
				new Execute().LoadXml();
			};

			timer.AutoReset = true;
			timer.Start();
		}

		protected override void OnStop() {
			timer.Stop();
		}
	}
}

```

####**4.サービスのインストール**
* 「installutil」コマンドを使用してサービスをインストールする。「VisualStudio 2015」フォルダから「開発者コマンドプロンプト for 2015」を「管理者として実行」する(「管理者として実行」をしないと、インストール時にエラーになる)。

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/184967/f67c9f26-d8fa-6ccb-6e35-8c3983007114.png)

![無題2.png](https://qiita-image-store.s3.amazonaws.com/0/184967/708151f2-82ac-c7bd-d746-aa7d4ca19c11.png)

正常にインストールされた場合、サービス一覧に登録される。
![無題3.png](https://qiita-image-store.s3.amazonaws.com/0/184967/aca736dc-ab69-534b-8822-74865b163547.png)

サービスを開始すると、xmlで設定したフォルダにファイルが作成され、時間間隔で時刻が書かれていると思います。

以上です。