设为首页 收藏本站
查看: 2567|回复: 0

实现客户端程序自动更新使用FTP

[复制链接]

尚未签到

发表于 2015-5-28 12:37:55 | 显示全部楼层 |阅读模式
  最近做的一个项目中需要用到客户端自动更新功能,最初的想法是利用ClickOnce技术来完成,但在实践中发现根本行不能,原因如下:
  1)项目应用到了DevExpress控件包,用ClickOnce发布的自动更新程序,客户在安装时报在GAC中找不到控件dll的错。
  2)ClickOnce安装无法实现根据用户安装时录入的参数(比如数据库服务器名、数据库用户名和密码等)来动态修改配置文件的功能。
  3)最后一下其实不重要了,就是ClickOnce无法实现用户自定义安装文件夹。
  最后决定放弃使用ClickOnce,使用ftp方式进行,实现思路如下:用户启动程序时,先运行update.exe,该文件会自动比较本地配置文件和ftp服务器上配置文件的异同,会自动下载上次更新后变化的文件以及新加入的文件。(因为都是基本配置文件,所以开发了一个配置文件生成工具,用户只需要选择根目录后,就会自动生成配置文件。)文件下载结束后,再启动实际的客户端程序。
  程序的主要代码如:
  1 DSC0000.gif using System;
  2using System.Collections.Generic;
  3using System.Diagnostics;
  4using System.IO;
  5using System.Net;
  6using System.Threading;
  7using System.Windows.Forms;
  8
  9namespace Update
10 DSC0001.gif DSC0002.gif DSC0003.gif {
11 DSC0004.gif DSC0005.gif     /**////
12 DSC0006.gif     /// Description:
13    /// Author: ZhangRongHua
14    /// Create DateTime: 2009-6-21 12:25
15    /// UpdateHistory:      
16 DSC0007.gif     ///
17    public partial class frmUpdate : Form
18    {
19        Fields#region Fields
20
21        private const string CONFIGFILE = "update.xml";
22        private const string UPDATEDIR = "PMS";
23        private string appPath = Application.StartupPath;
24        private List errorList = new List();
25        private string locFile = String.Concat(Application.StartupPath, "\\", CONFIGFILE);
26        private string tmpUpdateFile = "TmpUpdate.xml";
27        private List updateList;
28        private string updateTmpPath = string.Concat(Path.GetTempPath(), "\\", UPDATEDIR);   
29        private string url = String.Empty;
30
31        private FTP ftp = null;
32
33        #endregion
34
35        Delegates#region Delegates
36
37        public delegate void AsycDownLoadFile(string srcFile, string destFile, int i);
38
39        public delegate void ExecuteUpdateFiles(string srcPath, string destPath);
40
41        public delegate void UpdateComplete();
42
43        public delegate void UpdateUI(int i, string message);
44
45        #endregion
46
47        public event UpdateComplete OnUpdateComplete;
48
49        Constructor#region Constructor
50
51        public frmUpdate()
52        {
53            InitializeComponent();
54            OnUpdateComplete += new UpdateComplete(frmUpdate_OnUpdateComplete);
55        }
56
57        #endregion
58
59        Event Handler#region Event Handler
60
61        private void frmUpdate_Load(object sender, EventArgs e)
62        {
63           if(Directory.Exists(updateTmpPath))
64           {
65               Directory.Delete(updateTmpPath, true);
66           }
67         
68            // 如果有主程序启动,则关闭
69            Process[] ps = Process.GetProcesses();
70            foreach (Process p in ps)
71            {
72                //MessageBox.Show(p.ProcessName);
73                if (p.ProcessName.ToLower() == "wat.pms.winform")
74                {
75                    p.Kill();
76                    break;
77                }
78            }
79
80            GetUpdateFiles();
81        }
82
83        private void frmUpdate_OnUpdateComplete()
84        {
85            ExecuteUpdateFiles dExecuteUpdateFiles = new ExecuteUpdateFiles(ExecuteUpdate);
86            Invoke(dExecuteUpdateFiles, new object[] {updateTmpPath, appPath});
87        }
88
89        private void frmUpdate_Shown(object sender, EventArgs e)
90        {
91            Thread updateThread = new Thread(new ThreadStart(DownLoadUpdateFiles));
92            updateThread.SetApartmentState(ApartmentState.STA);
93            updateThread.IsBackground = true;
94            Thread.Sleep(500);
95            updateThread.Start();
96
97  
98         }
99
100        #endregion
101
102        Private Methods#region Private Methods
103
104         /**////
105         /// 将目标文件替换为本地文件
106         ///  
107         /// Author:ZhangRongHua
108         /// Create DateTime: 2009-6-21 10:28
109         /// Update History:     
110         ///  
111         ///
112         /// The SRC file.
113         /// The dest file.
114        private void DownLoadFile(string srcFile, string destFile)
115        {
116            if(ftp == null )
117            {
118                ftp = new FTP(Updater.URL, "", Updater.User, Updater.Password);
119            }
120
121           
122
123            if(!ftp.Connected)
124            {
125                MessageBox.Show("无法连接远程服务器,无法更新程序", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
126                Process.Start(Updater.MainProgram);
127                Close();
128               
129            }
130
131            // 得到服务器端的配置文件
132             ftp.Get(srcFile, updateTmpPath, destFile);
133
134         
135
136        }
137
138        /**////
139        /// 得到需要更新的文件清单
140        ///  
141        /// Author:ZhangRongHua
142        /// Create DateTime: 2009-6-21 10:29
143        /// Update History:     
144        ///  
145        ///
146        private void GetUpdateFiles()
147        {
148            Updater.GetBaseInfo(locFile);
149            url = Updater.URL;
150            string svrFile = String.Concat(url, CONFIGFILE);
151
152            if (String.IsNullOrEmpty(svrFile))
153            {
154                BroadCastOnUpdateComplete();
155                return;
156            }
157
158            Directory.CreateDirectory(updateTmpPath);
159            try
160            {
161                DownLoadFile(CONFIGFILE, tmpUpdateFile);
162            }
163            catch (Exception ex)
164            {
165                MessageBox.Show("无法连接远程服务器,无法更新程序", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
166                Process.Start(Updater.MainProgram);
167                Close();
168            }
169
170            updateList = Updater.GetUpdateFileList(locFile, tmpUpdateFile);
171            if (updateList == null || updateList.Count < 1)
172            {
173                BroadCastOnUpdateComplete();
174                return;
175            }
176
177            pbUpdate.Maximum = updateList.Count;
178            pbUpdate.Minimum = 0;
179            lblInfo.Text = String.Concat(updateList.Count, "个文件需要更新!");
180            lblInfo.BringToFront();
181            lblState.BringToFront();
182            lblInfo.Update();
183
184            pbUpdate.Maximum = updateList.Count;
185            pbUpdate.Minimum = 0;
186
187            for (int i = 0; i < updateList.Count; i++)
188            {
189                string file = updateList;
190                ListViewItem lvItem = new ListViewItem();
191                lvItem.Text = file;
192                lvItem.SubItems.Add(Updater.MainProgramVersion);
193                lvUpdateList.Items.Add(lvItem);
194            }
195        }
196
197        private void UpdateUIInfo(int i, string message)
198        {
199            pbUpdate.Value = i + 1;
200            lblState.Text = message;
201            lblState.Update();
202        }
203
204        private void BroadCastOnUpdateComplete()
205        {
206            if (OnUpdateComplete != null)
207            {
208                OnUpdateComplete();
209            }
210        }
211
212        private void DownLoadUpdateFiles()
213        {
214            if (updateList == null || updateList.Count < 1)
215            {
216                BroadCastOnUpdateComplete();
217                return;
218            }
219
220            try
221            {
222                UpdateUI dUpdateUI = new UpdateUI(UpdateUIInfo);
223                AsycDownLoadFile dAsycDownLoadFile = new AsycDownLoadFile(DownLoadFile);
224                for (int i = 0; i < updateList.Count; i++)
225                {
226                    string file = updateList;
227                    string destFile = String.Concat(updateTmpPath, "\\", file);
228                    string destFileName = destFile.Substring(destFile.LastIndexOf("/") + 1);
229                    string srcFile = String.Concat(url, file);
230                    var srcFileName = file.Trim('/');
231                    destFile = destFile.Replace("/", "\\");
232                    Directory.CreateDirectory(destFile.Substring(0, destFile.LastIndexOf("\\")));
233                    string curentFile = String.Concat("正在更新第", i + 1, "/", updateList.Count, "个", file);
234                  
235                    Invoke(dAsycDownLoadFile, new object[] { srcFileName, srcFileName, i });
236                    Thread.Sleep(50);
237                    Invoke(dUpdateUI, new object[] {i, curentFile});
238                }
239            }
240            catch (Exception ex)
241            {
242                Debug.WriteLine(ex.Message);
243            }
244
245            BroadCastOnUpdateComplete();
246        }
247
248        
249
250        private void CopyUpdateFiles(string srcPath, string destPath)
251        {
252            string[] files = Directory.GetFiles(srcPath);
253            for (int i = 0; i < files.Length; i++)
254            {
255                string srcFile = files;
256                string destFile = string.Concat(destPath, "\\", Path.GetFileName(srcFile));
257                try
258                {
259                    File.Copy(srcFile, destFile, true);
260                }
261                catch (System.IO.IOException  ex)
262                {
263                    
264                    
265                }
266                 
267            }
268
269            string[] dirs = Directory.GetDirectories(srcPath);
270            for (int i = 0; i < dirs.Length; i++)
271            {
272                srcPath = dirs;
273                string tmpDestPath = String.Concat(destPath, "\\", Path.GetFileName(srcPath));
274                Directory.CreateDirectory(tmpDestPath);
275                CopyUpdateFiles(srcPath, tmpDestPath);
276            }
277        }
278
279
280
281        /**////
282        /// 更新完成后,要执行的动作(将下载的文件从临时目录复制到主目录,重启主程序)
283        ///  
284        /// Author:ZhangRongHua
285        /// Create DateTime: 2009-6-21 12:25
286        /// Update History:     
287        ///  
288        ///
289        /// The SRC path.
290        /// The dest path.
291        private void ExecuteUpdate(string srcPath, string destPath)
292        {
293            if (errorList != null && errorList.Count < 1)
294            {
295                lblInfo.Text = "正在执行更新";
296                lblInfo.Update();
297                CopyUpdateFiles(srcPath, destPath);
298                File.Copy(tmpUpdateFile, locFile, true);
299            }
300            Process.Start(Updater.MainProgram);
301
302            Close();
303        }
304
305        private void DownLoadFile(string srcFile, string destFile, ListViewItem lvItem)
306        {
307            try
308            {
309                DownLoadFile(srcFile, destFile);
310                lvItem.SubItems.Add("Ok");
311             }
312            catch (Exception ex)
313            {
314                Debug.WriteLine(ex.Message);
315                lvItem.SubItems.Add("fail");
316                ErrorInfo errorInfo = new ErrorInfo();
317                errorInfo.File = srcFile;
318                errorInfo.ErrorLevel = ErrorLevel.Serious;
319                errorInfo.Message = ex.Message;
320                errorList.Add(errorInfo);
321            }
322        }
323
324        private void DownLoadFile(string srcFile, string destFile, int i)
325        {
326            ListViewItem lvItem = lvUpdateList.Items;
327
328            lvUpdateList.Items.EnsureVisible();
329            try
330            {
331                DownLoadFile(srcFile, destFile);
332                lvItem.SubItems.Add("Ok");
333            }
334            catch (Exception ex)
335            {
336                Debug.WriteLine(ex.Message);
337                lvItem.SubItems.Add("fail");
338                ErrorInfo errorInfo = new ErrorInfo();
339                errorInfo.File = srcFile;
340                errorInfo.ErrorLevel = ErrorLevel.Serious;
341                errorInfo.Message = ex.Message;
342                errorList.Add(errorInfo);
343                MessageBox.Show(destFile);
344            }
345        }
346
347        #endregion
348    }
349 DSC0008.gif }
  
出处:http://zhangronghua.iyunv.com

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-71510-1-1.html 上篇帖子: FTP 1 协议分析 下篇帖子: Windows FTP API
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表