珂珂的个人博客 - 一个程序猿的个人网站

winform一键发布工具

   由于现在做的系统是基于Winform的,在服务器上需要发布,挺麻烦的,而且改动一点点就得全部上传,忍耐了很久终于做了一个一键发布的工具。原理跟目录同步差不多,只不过要做一些特殊处理。先获取本地的最大版本号,再请求服务器更改,服务器把上面最新的版本复制一份到新版本文件夹(目的是保留老版本)。然后再跟目录同步工具一样,但要排除之前的版本文件夹。


同样,需要一个服务端ashx文件配合

using System;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Linq;
using System.Xml.Serialization;

namespace WebUpdate
{
    ///     /// AppPublish 的摘要说明
    ///     public class AppPublish : IHttpHandler
    {

        private HttpRequest Request;
        private HttpResponse Response;
        public void ProcessRequest(HttpContext context)
        {
            Request = context.Request;
            Response = context.Response;
            context.Response.ContentType = "text/plain";
            try
            {
                if (!String.IsNullOrEmpty(Request["remotePath"]))
                {
                    //复制
                    if (Request["action"] == "setmaxversion")
                    {
                        string dir = Path.GetDirectoryName(context.Server.UrlDecode(Request["remotePath"]));
                        if (!Directory.Exists(dir))
                        {
                            Directory.CreateDirectory(dir);
                            Response.Write("ok");
                            return;
                        }

                        string maxversion = GetMaxVersion(dir);
                        if (maxversion != null)
                        {
                            if (maxversion != Request["maxversion"])
                            {
                                //复制为最大版本
                                FileHelper.Copy(Path.Combine(dir, "Application Files", maxversion), Path.Combine(dir, "Application Files", Request["maxversion"]));
                            }
                        }

                        Response.Write("ok");
                    }

                    //列出数据
                    if (Request["action"] == "dir")
                    {
                        string appDir = context.Server.UrlDecode(Request["remotePath"]);
                        if (!Directory.Exists(appDir))
                        {
                            throw new Exception("远程目录不存在");
                        }

                        List list = new List();
                        LoadFile(list, appDir, appDir, false);

                        string maxversion = GetMaxVersion(appDir);
                        if (maxversion != null)
                        {
                            LoadFile(list, Path.Combine(appDir, "Application Files", maxversion), appDir, true);
                        }
                        XmlSerializer sz = new XmlSerializer(list.GetType());
                        sz.Serialize(Response.OutputStream, list);
                    }

                    //上传
                    if (Request["action"] == "upload")
                    {
                        string filePath = context.Server.UrlDecode(Request["remotePath"]);
                        string dir = Path.GetDirectoryName(filePath);
                        if (!Directory.Exists(dir))
                        {
                            Directory.CreateDirectory(dir);
                        }
                        Request.Files[0].SaveAs(filePath);
                        Response.Write("上传成功" + filePath);
                    }
                }
            }
            catch (Exception ex)
            {
                Response.Write(ex.Message);
            }
        }

        public class FileMessage
        {
            public long Size { get; set; }

            public string Sha1 { get; set; }

            public string FileName { get; set; }
        }

        private void LoadFile(List list, string p, string baseDir, bool isLocaChild)
        {
            foreach (string file in Directory.GetFiles(p))
            {
                list.Add(GetFileInfo(file, baseDir));
            }

            if (isLocaChild)
            {
                foreach (string folder in Directory.GetDirectories(p))
                {
                    LoadFile(list, folder, baseDir, isLocaChild);
                }
            }
        }

        private string GetMaxVersion(string dirPath)
        {
            List list = new List();
            if (!Directory.Exists(Path.Combine(dirPath, "Application Files")))
            {
                Directory.CreateDirectory(Path.Combine(dirPath, "Application Files"));
            }
            foreach (string dir in Directory.GetDirectories(Path.Combine(dirPath, "Application Files")))
            {
                list.Add(Path.GetFileName(dir));
            }

            if (list.Count > 0)
            {
                return list.Max();
            }

            return null;
        }

        ///         /// 获取文件信息
        ///         private FileMessage GetFileInfo(String filePath, string baseDir)
        {
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            long lenth = fs.Length;
            System.Security.Cryptography.HashAlgorithm algorithm = System.Security.Cryptography.SHA1.Create();
            String result = BitConverter.ToString(algorithm.ComputeHash(fs)).Replace("-", "");
            fs.Close();
            return new FileMessage { Size = lenth, Sha1 = result, FileName = filePath.Replace(baseDir, "").TrimStart('\\').TrimStart('/') };
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}


xml配置文件

     http://leeup.fyj.me/AppPublish.ashx     C:\发布\HAK-leemap\    E:\HAK\Setup\


处理逻辑

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;

namespace AppPublish
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        public delegate void Action();

        public void SafeCall(Control ctrl, Action callback)
        {
            if (ctrl.InvokeRequired)
                ctrl.Invoke(callback);
            else
                callback();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
            XmlDocument doc = new XmlDocument();
            doc.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "publish.config.xml"));
            List list = new List();
            foreach (XmlNode node in doc.SelectNodes("/publish/app"))
            {
                list.Add(node.Attributes["name"].InnerText);
            }
            this.comboBox1.DataSource = list;
        }

        ///         /// 获取本地最大版本
        ///         ///         ///         private string GetLocalMaxVersion(string localPath)
        {
            List list = new List();
            foreach (string dir in Directory.GetDirectories(Path.Combine(localPath, "Application Files")))
            {
                list.Add(Path.GetFileName(dir));
            }

            if (list.Count > 0)
            {
                return list.Max();
            }

            return null;
        }

        private void btnPublish_Click(object sender, EventArgs e)
        {
            this.btnPublish.Text = "发布中...";
            this.btnPublish.Enabled = false;

            XmlDocument doc = new XmlDocument();
            doc.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "publish.config.xml"));
            XmlNode appnode = doc.SelectSingleNode("/publish/app[@name='" + this.comboBox1.Text + "']");
            string publishUrl = appnode.SelectSingleNode("publishUrl").InnerText;

            string localFolder = null;
            if (appnode.SelectSingleNode("localFolder") != null)
            {
                localFolder = appnode.SelectSingleNode("localFolder").InnerText;
            }

            string remoteFolder = null;
            if (appnode.SelectSingleNode("remoteFolder") != null)
            {
                remoteFolder = appnode.SelectSingleNode("remoteFolder").InnerText;
            }

            XmlNodeList nlist = appnode.SelectNodes("file");
            this.progressBar1.Value = 0;
            ThreadPool.QueueUserWorkItem((o) =>
            {
                try
                {
                    this.txtStatus.Text = "正在获取本地信息...";
                    //本地文件信息
                    List localList = new List();
                    LoadFile(localList, localFolder, localFolder, false);
                    string maxversion = GetLocalMaxVersion(localFolder);
                    if (maxversion != null)
                    {
                        LoadFile(localList, Path.Combine(localFolder, "Application Files", maxversion), localFolder, true);
                    }

                    this.txtStatus.Text = "正在请求服务器更改最大版本...";
                    WebClient wc = new WebClient();
                    string result = wc.DownloadString(publishUrl + "?remotePath=" + System.Web.HttpUtility.UrlEncode(remoteFolder) + "&action=setmaxversion&maxversion=" + maxversion);
                    if (result.Trim() != "ok")
                    {
                        this.SafeCall(this.listBox1, () =>
                        {
                            this.listBox1.Items.Add("请求服务器更改最大版本错误:server返回" + result);
                        });
                        this.txtStatus.Text = "同步出错";
                        return;
                    }

                    this.txtStatus.Text = "正在从服务器获取数据...";
                    XmlSerializer sz = new XmlSerializer(typeof(List));
                    //服务器文件信息
                    List serverList = (List)sz.Deserialize(wc.OpenRead(publishUrl + "?remotePath=" + System.Web.HttpUtility.UrlEncode(remoteFolder) + "&action=dir"));

                    this.txtStatus.Text = "正在处理...";
                    //需要同步的文件列表
                    List syncList = new List();

                    foreach (FileMessage fm in localList)
                    {
                        FileMessage srcFm = GetFileMessage(serverList, fm.FileName);
                        //如果服务器上不存在该文件  则需同步
                        if (srcFm == null)
                        {
                            string url = publishUrl + "?remotePath=" + System.Web.HttpUtility.UrlEncode(Path.Combine(remoteFolder, fm.FileName)) + "&action=upload";
                            syncList.Add(new UploadMessage
                            {
                                UploadUrl = url,
                                LocalPath = Path.Combine(localFolder, fm.FileName),
                                RemoteFileName = Path.Combine(remoteFolder, fm.FileName),
                                Size = fm.Size
                            });
                        }
                        else
                        {
                            //如果不等于服务器上的sha1  则需要同步
                            if (!srcFm.Sha1.Equals(fm.Sha1, StringComparison.CurrentCultureIgnoreCase))
                            {
                                string url = publishUrl + "?remotePath=" + System.Web.HttpUtility.UrlEncode(Path.Combine(remoteFolder, fm.FileName)) + "&action=upload";

                                syncList.Add(new UploadMessage
                                {
                                    UploadUrl = url,
                                    LocalPath = Path.Combine(localFolder, fm.FileName),
                                    RemoteFileName = Path.Combine(remoteFolder, fm.FileName),
                                    Size = fm.Size
                                });
                            }
                        }
                    }


                    foreach (FileMessage fm in serverList)
                    {
                        FileMessage destFm = GetFileMessage(localList, fm.FileName);
                        //如果客户端不存在该文件  则需删除服务器上的     
                        if (destFm == null)
                        {
                            IDictionary dic = new Dictionary();

                            string url = publishUrl + "?remotePath=" + System.Web.HttpUtility.UrlEncode(Path.Combine(remoteFolder, fm.FileName)) + "&action=upload";

                            syncList.Add(new UploadMessage
                            {
                                UploadUrl = url,
                                RemoteFileName = Path.Combine(remoteFolder, fm.FileName),
                                IsDelete = true
                            });
                        }
                    }

                    if (syncList.Count == 0)
                    {
                        MessageBox.Show("已经同步好了。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        this.btnPublish.Text = "发布";
                        this.btnPublish.Enabled = true;
                        this.txtStatus.Text = "就绪";
                        return;
                    }

                    //计算总同步大小
                    long total = 0;
                    foreach (UploadMessage d in syncList)
                    {
                        total += d.Size;
                    }

                    this.SafeCall(this.progressBar1, () =>
                    {
                        this.progressBar1.Maximum = (int)total;
                    });

                    foreach (UploadMessage mess in syncList)
                    {
                        try
                        {
                            if (mess.IsDelete)
                            {
                                //不删除服务器根目录
                                if (mess.RemoteFileName.Contains("Application Files"))
                                {
                                    this.txtStatus.Text = "正在删除服务器文件" + mess.RemoteFileName;
                                    wc = new WebClient();
                                    string d = wc.DownloadString(mess.UploadUrl);
                                    this.SafeCall(this.listBox1, () =>
                                    {
                                        this.listBox1.Items.Add(d);
                                    });
                                    continue;
                                }
                            }
                            else
                            {
                                string localFile = mess.LocalPath;
                                this.txtStatus.Text = "正在上传" + localFile;
                                string url = mess.UploadUrl;

                                //WebClient wb = new WebClient();
                                //byte[] b = wb.UploadFile(url, localFile);
                                //string result = System.Text.Encoding.UTF8.GetString(b);
                                //this.SafeCall(this.listBox1, () =>
                                //{
                                //    this.listBox1.Items.Add(result);
                                //});

                                HttpUploadHelper up = new HttpUploadHelper();
                                up.UploadStenEvent += up_UploadStenEvent;
                                up.CompleteEvent += up_CompleteEvent;
                                up.Upload_Request(url, localFile, mess.RemoteFileName);
                            }
                        }
                        catch (Exception ex)
                        {
                            this.SafeCall(this.listBox1, () =>
                            {
                                this.listBox1.Items.Add(ex.Message);
                            });

                            this.SafeCall(this.txtErrorCount, () =>
                            {
                                this.txtErrorCount.Text = (Convert.ToInt32(txtErrorCount.Text) + 1).ToString();
                            });
                        }
                    }

                    MessageBox.Show("发布完成。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    this.txtStatus.Text = "就绪";
                    this.btnPublish.Text = "发布";
                    this.btnPublish.Enabled = true;
                }
                catch (Exception ex)
                {
                    this.SafeCall(this.listBox1, () =>
                    {
                        this.listBox1.Items.Add(ex.Message);
                    });

                    this.txtStatus.Text = "同步出错";
                    this.btnPublish.Text = "发布";
                    this.btnPublish.Enabled = true;
                }
            });
        }

        void up_CompleteEvent(string result)
        {
            this.SafeCall(this.listBox1, () =>
            {
                this.listBox1.Items.Add(result);
            });
        }

        ///         /// 获取文件信息
        ///         private FileMessage GetFileInfo(String filePath, string baseDir)
        {
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            long lenth = fs.Length;
            System.Security.Cryptography.HashAlgorithm algorithm = System.Security.Cryptography.SHA1.Create();
            String result = BitConverter.ToString(algorithm.ComputeHash(fs)).Replace("-", "");
            fs.Close();
            return new FileMessage { Size = lenth, Sha1 = result, FileName = filePath.Replace(baseDir, "") };
        }

        private void LoadFile(List list, string p, string baseDir, bool isIncludeChild)
        {
            foreach (string file in Directory.GetFiles(p))
            {
                if (file.Contains("publish.config.xml"))
                {
                    continue;
                }

                list.Add(GetFileInfo(file, baseDir));
            }

            if (isIncludeChild)
            {
                foreach (string folder in Directory.GetDirectories(p))
                {
                    LoadFile(list, folder, baseDir, isIncludeChild);
                }
            }

        }

        private FileMessage GetFileMessage(List list, string fileName)
        {
            foreach (FileMessage fm in list)
            {
                if (fm.FileName.Equals(fileName, StringComparison.CurrentCultureIgnoreCase))
                {
                    return fm;
                }
            }

            return null;
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            this.listBox1.Items.Clear();
            //HttpUploadHelper up = new HttpUploadHelper();
            //up.UploadStenEvent += up_UploadStenEvent;
            //up.Upload_Request("http://www.leemap.com:9999/AppPublish.ashx?remotePath=" + System.Web.HttpUtility.UrlEncode("e:\\iTran.CargoPlus.Face.exe"), @"D:\ZUHCargoPlus\iTran.CargoPlus.Face\bin\Debug\iTran.CargoPlus.Face.exe", "iTran.CargoPlus.Face.exe");
        }

        void up_UploadStenEvent(UploadEvent e)
        {
            this.SafeCall(this.progressBar1, () =>
            {
                this.progressBar1.Value = this.progressBar1.Value += e.CurrentSize;
            });

            this.SafeCall(this.txtSizeStatus, () =>
            {
                this.txtSizeStatus.Text = this.progressBar1.Value + "/" + this.progressBar1.Maximum;
            });
        }

        protected override void WndProc(ref Message SystemMessage)
        {
            switch (SystemMessage.Msg)
            {
                case 0x0112:
                    if (((int)SystemMessage.WParam) == 61536)
                    {
                        // this.Owner.Close();
                        Application.ExitThread();
                    }
                    else
                    {
                        base.WndProc(ref SystemMessage);
                    }
                    break;
                default:
                    base.WndProc(ref SystemMessage);
                    break;
            }
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }
    }

    public class UploadMessage
    {
        public long Size { get; set; }

        public string Sha1 { get; set; }

        public string LocalPath { get; set; }

        public string UploadUrl { get; set; }

        public string RemoteFileName { get; set; }

        public bool IsDelete { get; set; }
    }

    public class FileMessage
    {
        public long Size { get; set; }

        public string Sha1 { get; set; }

        private string _fileName;
        public string FileName
        {
            get
            {
                return (_fileName == null ? null : _fileName.TrimStart('\\').TrimStart('/'));
            }
            set
            {
                _fileName = value;
            }
        }
    }
}



上一篇:多线程域名查询工具

下一篇:个人代码全部开源


0 评论

查看所有评论

给个评论吧