【C#】使用SVN鉤子自動更新服務器

博客重建工作一切從0開始,萬事開頭難,期間很多想法想來簡單,但付諸實踐卻很是棘手。

服務器是Win2012 R2 + IIS7

我所使用的SVN服務商是免費的SVNBucket,它提供了一個很給力的功能,SVN鉤子,意思就是每次Commit後,SVNBucker那邊自動訪問這個url,你的web服務器就可以接收到,然後觸發你自己寫的功能,比如更新SVN或者其他東西,達到服務器自動同步的目的,也就不用再沙雕的在服務器上每1分鐘自動更新,浪費本就可憐的內存。

目錄

 

失敗的方案:

成功的方案:


失敗的方案:

最開始的想法是寫個batch,然後控制器觸發CMD調用。

批處理內容:

svn update D:\Web1
svn update D:\Web2

控制器內容: 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Diagnostics;
using System.IO;

namespace Web.Controllers
{
    public class TestController : Controller
    {
        public String Update()
        {
            WindowsTools t = new WindowsTools();
            var str = t.RunCmd2(@"D:\SVNupdate.bat").ToString();
            return str;
        }
    }

    public class WindowsTools
    {
        /// <summary>
        /// 運行cmd命令
        /// 不顯示命令窗口
        /// </summary>
        /// <param name="cmdExe">指定應用程序的完整路徑</param>
        public string RunCmd2(string cmdExe)
        {
            try
            {
                using (Process myPro = new Process())
                {
                    myPro.StartInfo.FileName = "cmd.exe";
                    myPro.StartInfo.UseShellExecute = false;
                    myPro.StartInfo.RedirectStandardInput = true;
                    myPro.StartInfo.RedirectStandardOutput = true;
                    myPro.StartInfo.RedirectStandardError = true;
                    myPro.StartInfo.CreateNoWindow = true;
                    myPro.Start();
                    myPro.StandardInput.WriteLine(cmdExe);
                    myPro.StandardInput.AutoFlush = true;
                    myPro.StandardInput.WriteLine("exit");
                    string outStr = myPro.StandardOutput.ReadToEnd();
                    myPro.Close();
                    return outStr;
                }
            }catch(Exception e)
            {
                return e.Message;
            }
            
        }

    }
}

看起來一切都那麼美好,但是,線上環境的cmd調用始終有問題,就是無法觸發。

控制器返回結果:

Microsoft Windows [版本 10.0.17763.775]
(c) 2018 Microsoft Corporation。保留所有權利。

C:\\windows\\sytstem32\\inetsrv>D:\\SVNupdate.bat.bat

C:\\windows\\sytstem32\\inetsrv>svn update D:\\Web1

C:\\windows\\sytstem32\\inetsrv>svn update D:\\Web2

C:\\windows\\sytstem32\\inetsrv>exit

執行完【svn update】後竟是一片空白。。。。。

無奈各種資料查閱,猜測原因是權限問題。

於是查閱到了一篇關於解決權限的IIS設置解決方案:https://www.cnblogs.com/yuyuko/p/10697856.html 

設置後再加服務器重啓,還是不行,包括文件上給足權限,cmd給足權限,快捷方式扔windows32目錄, 各種折騰後,我放棄了。。。

實在是太無奈了,爲了體驗下SVN鉤子神奇的功能,只能逼我大招了。。。

我想到了另一個解決方法。進程間通信。。。


成功的方案:

【終極方案】

首先,另寫一個控制檯exe程序,24小時運行在服務器上,並把這個小程序的快捷方式扔進【C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp】這個目錄(開機啓動項目錄),然後最小化運行就行了。

using System;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Threading;

namespace updatesvn
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread receiveDataThread = new Thread(ReceiveDataFromClient);
            receiveDataThread.IsBackground = true;
            receiveDataThread.Start();
            receiveDataThread.Join();
        }

        private static NamedPipeServerStream _pipeServer;
        private static void ReceiveDataFromClient()
        {
            while (true)
            {
                try
                {
                    _pipeServer = new NamedPipeServerStream("svnPipe", PipeDirection.InOut, 2);
                    _pipeServer.WaitForConnection(); //Waiting  
                    StreamReader sr = new StreamReader(_pipeServer);
                    string recData = sr.ReadLine();
                    if (recData == "update"){
                        System.Diagnostics.Process.Start(@"D:\SVNupdate.bat");
                    }else if(recData == "Exit"){
                        Console.WriteLine("Pipe Exit.");
                        Process.GetCurrentProcess().Kill();
                    }

                    Console.WriteLine(recData + DateTime.Now.ToString());
                    Thread.Sleep(1000);
                    sr.Close();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }

    }
}

C#.net 控制器代碼:

using System;
using System.Web.Mvc;
using Web.Tools;

namespace Web.Controllers
{
    public class SVNUpdateController : Controller
    {
        public String Update()
        {
            var b = WindowsTools.SendUpdate().ToString();
            return b+DateTime.Now.ToString();
        }
    }

}

 另附一個C#.net 管道通信工具類

using System.IO;
using System.IO.Pipes;
using System.Security.Principal;

namespace Web.Tools
{
    public class WindowsTools
    {
        private static NamedPipeClientStream _pipeClient;
        public static bool SendData(string cmd)
        {
            try
            {
                _pipeClient = null;
                _pipeClient = new NamedPipeClientStream(".", "svnPipe", PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.Impersonation);
                _pipeClient.Connect();
                StreamWriter sw = new StreamWriter(_pipeClient);
                sw.WriteLine(cmd);
                sw.Flush();
                sw.Close();
                return true;
            }
            catch {
                return false;
            }
        }
        public static bool SendUpdate() {
            return SendData("update");
        }
    }
}

大功告成。SVN鉤子測試成功。如果以後有更好的方案,我再回來補充上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章