いろいろ備忘録日記

主に .NET と Python絡みのメモを公開しています。

MS-DTCサービス起動・終了管理クラス

ADO.NET2.0にて、新たに追加されているTransactionScope等を使用する場合
MS-DTCサービスが起動していないとエラーとなります。

でも、実際にアプリを配布する対象のマシンのサービスを起動してくださいって
頼むのも大変ですので、アプリが動いている間だけ起動しておいてほしいな
って感じですね。てことで、ちょろっと作ってみました。
めっちゃ簡素な作りになっていますがご勘弁を。一応、個人的には使えているので
オッケイかなとw


Permission周りとか全然考慮していませんので、権限が弱いと多分エラーでます。w


以下のような感じです。

using System;
using System.ServiceProcess;

namespace Gsf.Lib.ServiceControl {

    /// 
    /// MS-DTCサービスの起動と終了を管理するクラスです。
    /// 
    /// 
    /// 本クラスは、ADO.NET2.0のトランザクション機能を利用する為に必要なMS-DTCサービスの
    /// 起動・終了を管理します。
    /// 
    /// Startメソッドで開始。Stopメソッドで停止します。
    /// 
    /// 前提条件として、以下の事柄が存在します。
    /// (1) 既に起動している場合は何もしません。
    /// (2) 停止処理は、開始する前の状態が停止処理であった場合のみ行われます。
    ///   (つまり、元の状態に戻します。)
    /// (3) 開始・停止以外のステータスには対応していません。
    /// 
    /// 本クラスは、IDisposableインターフェースを実装していますので
    /// usingブロックにて使用できます。その際、ブロックを抜けるときに
    /// Stopメソッドがコールされます。
    /// 
    /// 以下、利用例です。
    /// 
    /// using(MSDTCServiceController serviceController = new MSDTCServiceController()){
    ///         処理.....
    /// }
    /// 
    /// 
    public class MSDTCServiceController : IServiceController, IDisposable {

        /// 
        /// サービス名
        /// 
        const string SERVICE_NAME = "MSDTC";

        /// 
        /// 元々のサービスの状態
        /// 
        /// 
        /// 初期値はデフォルトで停止状態でセットされています。
        /// 
        protected ServiceControllerStatus _initialStatus = ServiceControllerStatus.Stopped;
        /// 
        /// 停止処理が既に行われているか否か。
        /// 
        protected bool _isStopped = false;

        /// 
        /// デフォルトコンストラクタ
        /// 
        /// 
        /// 自動起動モードをONにして、クラスを構築します。
        /// 
        public MSDTCServiceController()
            : this(true) {
            // nop;
        }

        /// 
        /// コンストラクタ
        /// 
        /// 
        /// 自動起動を行うか否かを指定できるコンストラクタです。
        /// 
        /// 自動起動を行うか否か
        public MSDTCServiceController(bool autoStartUp) {
            if(autoStartUp) {
                Start();
            }
        }

        /// 
        /// サービスを開始します。
        /// 
        /// 
        /// 元々の状態が停止状態の場合のみ、サービス起動を行います。
        /// 
        public void Start() {

            using(ServiceController service = new ServiceController(SERVICE_NAME)) {

                if*1 {

                    if(service.Status == ServiceControllerStatus.Running) {
                        service.Stop();
                        service.WaitForStatus(ServiceControllerStatus.Stopped);

                        _isStopped = true;
                    }
                }
            }
        }

        /// 
        /// データの破棄処理を行います。
        /// 
        /// 
        /// このメソッドは、内部でStopメソッドを呼び出します。
        /// 
        /// Stopメソッドが呼ばれる条件は以下の通りです。
        /// (1) まだ、Stopメソッドが呼ばれていない場合
        /// 
        public void Dispose() {

            if(!_isStopped) {
                Stop();
            }
        }

    }

}


使い方としては、usingブロックで囲って使うのが一番簡単です。

using(MSDTCServiceController sc = new MSDTCServiceController()){
    xxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxx
}

みたいな感じで。


【追記】
上記のクラスをユーザグループがPowerUserのユーザで実行すると、起動はできるけど停止が出来ないです・・・・。
admin権限がやっぱり必要??

*1:_initialStatus = service.Status) == ServiceControllerStatus.Stopped) { service.Start(); service.WaitForStatus(ServiceControllerStatus.Running); } } } ///

/// サービスを停止します。 /// /// /// 以下の条件の場合のみ、停止処理を行います。 /// (1) 元の状態が停止状態であった。 /// (2) 現在のサービスの状態が起動中である。 /// public void Stop() { if(_initialStatus == ServiceControllerStatus.Stopped) { using(ServiceController service = new ServiceController(SERVICE_NAME