2020年9月6日日曜日

1: WindowsサービスをIDEなしで作成する

<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>

いかなるVisual Studio IDEもいかなるIDEも、C# Windowsサービスを作成するのに全然必要ない。

話題


About: C#

この記事の目次


開始コンテキスト


  • 読者は、C#プログラミングの基本的知識を持っている。

ターゲットコンテキスト



  • 読者は、何らのIDEもなしにWindowsサービスを作成する方法を理解する。

オリエンテーション


Hypothesizer 7
私はあるWindowsサービスを作成したい。

実は、かつて遠い昔に、あるWindowsサービスをC++で、Win32 APIを使用して作成したことがある。しかし、それが、今でも、選ぶべき方法なのだろうか?

インターネットで検索したところ、WindowsサービスをC#で作成する方法の多くの説明を見つけた、Visual Studio IDEを使用する方法であれば. . .

えーと、私は、何らのVisual Studio IDEも何らのIDEを使用しておらず、今から使い始めたくもない。

なぜか?えーと、多くの理由がある。1つには、使用するように強いられる付属のソースファイルエディタが好きじゃない: ソースファイルエディタは開発体験の決定的要素であり、私は自分の好みのエディタ('vim'である)を使いたい。また、IDEが生成するコードが好きじゃない、特に、頼みもしないのに付け加えられる不必要な安ピカ物たちが: 私は、自分のコードを自分の意図する通りにしたい。また、典型的なIDEの重さが好きじゃない: そのような重さが問題にならないほど、私のコンピュータは速くない。

いずれにせよ、必要なファイルに必要なコードさえ書けば、それでオーケーなはずだ。

面倒じゃないのかって?実は、判明したことには、とても容易なのだ。


本体


1: 何らのIDEもなしにWindowsサービスを作成する方法


Hypothesizer 7
Windowsサービスを作成するのに、何らのIDEも必要ない。

以下は、最小限Windowsサービスだ。

theBiasPlanet/officeWindowsService/programs/OfficeWindowsService.cs

@C# ソースコード
namespace theBiasPlanet {
	namespace officeWindowsService {
		namespace programs {
			using System;
			using System.ServiceProcess;
			
			// Register this Windows service by this command.
			// sc create OfficeWindowsService start={auto | demand} binpath="%path%"  obj=%the computer name%\%the user name% password=%the user password%
			public sealed class OfficeWindowsService : ServiceBase {
				public static void Main (String [] a_argumentsArray) {
					OfficeWindowsService l_officeWindowsService = new OfficeWindowsService (a_argumentsArray);
					if (Environment.UserInteractive) {
						l_officeWindowsService.OnStart (new String [] {}); 
						Console.Out.WriteLine ("### Press any key to stop this Windows service.");
						Console.Read ();
						l_officeWindowsService.OnStop ();
						Environment.Exit (0);
					}
					else {
						Run (l_officeWindowsService);
					}
				}
				
				public OfficeWindowsService (String [] a_argumentsArray) {
					ServiceName = "OfficeWindowsService";
				}
				
				~OfficeWindowsService () {
				}
				
				protected override void OnStart (String [] a_argumentsArray) {
					base.OnStart (a_argumentsArray);
				}
				
				protected override void OnStop () {
					base.OnStop ();
				}
			}
		}
	}
}

それだけ?そう、それで既に動作可能なWindowsサービスになっている。

初期化は、'OnStart (String [] a_argumentsArray)'メソッドに書かれている。終了化は、'OnStop ()'メソッドに書かれている。


2: Windowsサービスを登録する


Hypothesizer 7
以下のコマンドは、Windowsサービスを登録する、Windowsサービスユーザー名およびパスワードを指定して('LocalSystem'がユーザーの時、パスワードは不要)。

@cmd ソースコード
sc create OfficeWindowsService start=demand binpath="%path%" obj=%the computer name%\%the user name% password=%the user password%


3: Windowsサービスに引数群をセットする


Hypothesizer 7
Windowsサービスにいくつかの引数をセットしたい。つまり、Windowsサービスが開始する時にはいつも、それらの指定された引数を取るようにしたい。

Windowsサービス設定ダイアログを見たところ、「Start parameters(開始パラメータ)」とラベルが付けられたテキストボックスを見つけた。しかしながら、そこにいくつかの引数を入力してそのダイアログをクローズした後、それらの引数は保持されない。. . . この設定項目は何なのだ?. . .判明したことには、この設定項目は、単一回だけ引数を渡すためのもので、それは、私の望むものではない。

結局、引数群は、Windowsサービス登録コマンドにて指定しなければならない、以下のように。

@cmd ソースコード
sc create OfficeWindowsService start=demand binpath="%path% %argument0% %argument1%" obj=%the computer name%\%the user name% password=%the user password%

私のWindowsサービスは、それらの引数群を、'Main (String [] a_argumentsArray)'メソッドの引数群として受け取れる、'OnStart (String [] a_argumentsArray)'メソッドの引数群としてではなく。


4: Windowsイベントログシステムにログを書く


Hypothesizer 7
イベントログシステムにログを書くためには、Windowsイベントログシステム内にイベントソースを作成しなければならないが、それは、別のプログラムで1度だけ行なえばよいことだ。

実のところ、私は、以下のプログラムを作成した。

@C# ソースコード
namespace theBiasPlanet {
	namespace windowsEventLogSourceCreateor {
		namespace programs {
			using System;
			using System.Diagnostics;
			
			public sealed class WindowsEventLogSourceCreateor {
				public static void Main (String [] a_argumentsArray) {
					try {
						String l_eventLogSourceName;
						String l_eventLogSourceCategory = "Application";
						if (a_argumentsArray.Length < 1) {
							throw new Exception ("The arguments have to be these.\nThe argument 1: the event log source name\nThe argument 2: the category of the event source (the default is 'Application')");
						}
						l_eventLogSourceName = a_argumentsArray [0];
						if (a_argumentsArray.Length > 1) {
							l_eventLogSourceCategory = a_argumentsArray [1];
						}
						if (!EventLog.SourceExists (l_eventLogSourceName)) {
							EventLog.CreateEventSource (l_eventLogSourceName, l_eventLogSourceCategory);
						}
                        Environment.Exit (0);
                    }
                    catch (Exception l_exception) {
						Console.Error.WriteLine (l_exception);
                        Environment.Exit (1);
                    }
				}
			}
		}
	}
}

すると、Windowsサービス内では、ログは、以下のように書かれる。

@C# ソースコード
			using System.Diagnostics;
			
					EventLog.WriteEntry ("The service is starting up.", EventLogEntryType.Information);


5: 'ProjectInstaller'はどうなったのか?


Hypothesizer 7
実のところ、'ProjectInstaller'は、Windowsを'sc.exe'コマンドでインストールするには不要だ(そして、役に立たない): それは、Windowsサービスを'InstallUtil.exe'コマンドでインストールするためのものだ。

'InstallUtil.exe'を使うべきだと主張する一部の人々がいるが、'InstallUtil.exe'を使用する必要性を私は少しも感じない。.


6: 結びとその先


Hypothesizer 7
これで、Windowsサービスを、何らのIDEもなしに作成する方法を理解したようだ。

それは、とても容易だ。

そして、何らのIDEにも不明瞭にされていないコードを持つのは、とても快い。.

実のところ、本記事は、あるオフィス(LibreOfficeまたはApache OpenOffice)Windowsサービスを作成するための準備である。


参考資料


  • N/A. (N/A). Sc create | Microsoft Docs. Retrieved from https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/sc-create
<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>