読者です 読者をやめる 読者になる 読者になる

謎言語使いの徒然

適当に気になった技術や言語を流すブログ。

WCF で、バッチファイルをリモートで動かしてみた。

日記 .NET Tips

何か昔作ったサービスが古いフォルダから出てきた。
リモートで適当な登録済みバッチファイルを動かすだけ。
セキュリティとかガン無視してます。
WCF だから、適当に認証設定するといいよ!

インターフェース

namespace RunBatService
{
    /// <summary>
    /// バッチファイルを実行するためのインターフェースです。
    /// </summary>
    [ServiceContract]
    public interface IBatService
    {
        /// <summary>
        /// バッチを実行するプログラム部です。
        /// </summary>
        /// <param name="argument">バッチを指定する引数です。</param>
        [OperationContract]
        void ExecuteBatfile(BatfileArguments argument);
    }

    /// <summary>
    /// リモートでバッチファイルを指定する引数です。
    /// </summary>
    [DataContract]
    public class BatfileArguments
    {
        string batFileID;
        List<string> arguments;

        [DataMember]
        public string BatFileID
        {
            get { return this.batFileID; }
            set { this.batFileID = value; }
        }

        [DataMember]
        public List<string> Arguments
        {
            get { return this.arguments; }
            set { this.arguments = value; }
        }
    }
}


実装

namespace RunBatService
{
    // メモ: ここでクラス名 "Service1" を変更する場合は、App.config で "Service1" への参照も更新する必要があります。
    public class BatService : IBatService
    {
        private static Dictionary<string, string> dictionary;
        private static object syncObj;
        private static string baseDir;

        static BatService()
        {
            baseDir = ".\\";
            if (System.Configuration.ConfigurationManager.AppSettings.AllKeys.Contains("batpath"))
            {
                baseDir = System.Configuration.ConfigurationManager.AppSettings["batpath"];
            }

            baseDir = System.IO.Path.GetFullPath(baseDir);

            string resourceDir = baseDir + "\\batmapping.xml";

            dictionary = new Dictionary<string, string>();
            syncObj = new object();

            XmlDocument document = new XmlDocument();
            document.Load(resourceDir);
            XmlNodeList mapDatas = document.SelectNodes("/maps/mapdata");

            lock (BatService.syncObj)
            {
                foreach (XmlNode data in mapDatas)
                {
                    string id = data.Attributes["id"].Value;
                    string value = data.InnerText;
                    dictionary.Add(id, value);
                }
            }
        }

        #region IBatService メンバ

        public void ExecuteBatfile(BatfileArguments argument)
        {
            lock (BatService.syncObj)
            {
                Console.WriteLine("Received tasks: {0}", argument.BatFileID);
                if (BatService.dictionary.ContainsKey(argument.BatFileID))
                {
                    string targetFile = baseDir + "\\" +  BatService.dictionary[argument.BatFileID];
                    string argumentLine = string.Empty;

                    if (argument.Arguments != null)
                    {
                        foreach (string arg in argument.Arguments)
                        {
                            argumentLine += " " + arg;
                        }
                    }

                    System.Environment.CurrentDirectory = baseDir;
                    System.Diagnostics.Process.Start(targetFile, argumentLine);
                }
            }
        }

        #endregion
    }
}

設定(app.config)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="basicHttp_IBatService" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                    useDefaultWebProxy="true">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <security mode="None">
                        <transport clientCredentialType="None" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="UserName" algorithmSuite="Default" />
                    </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8400/BatRunnerService" binding="basicHttpBinding"
                bindingConfiguration="basicHttp_IBatService" contract="BatfileService.IBatService"
                name="basicHttp_IBatService" />
        </client>
    </system.serviceModel>
</configuration>

サーバ

namespace ServiceTestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            using (System.ServiceModel.ServiceHost host
                = new System.ServiceModel.ServiceHost(typeof(RunBatService.BatService)))
            {
                Console.WriteLine("Service startup...");
                host.Open();

                Console.WriteLine("Push enter to exit server.");
                Console.ReadLine();

                host.Close();
            }
        }
    }
}

クライアントは、、、、作れるだろ?