您的位置:首页 > 其它

共享WinCE6.0 下的一个软件升级程序

2012-12-17 09:20 579 查看
需求场境
厂里搞了几把PDA扫描枪,用来对下料工序进行扫描确认,本来以为就几把,直接连到电脑上用ActiveSync复制程序上去就好了,但是刚开发的程序一天要改个好几次,把枪收回来,装好再拿回去,一天做个4,5次简直叫人抓狂了。于是就决定自己整个简单的更新程序.

基本设计
1.要发布到WinCE上的程序比较简单,每个文件也比较小(都在500KB以下)所以决定直接让WebService 返回byte[]类型的文件内容然后在WinCE里写下文件,
另外也提供GetFile.ashx页面,里面使用Response.TransmitFile(path)以供客户端下载比较大的文件,当然在局域网环境下网速不是问题.

2.版本方面,不打算搞成每个文件都有一个版本,而是一个总版本,只要本地版本号小于服务器端版本号那么就下载服务器上的文件覆盖本地全部文件,
服务端与本地升级程序都有个配置文件来记录当前版本。

3.服务端使用IIS,不使用数据库,在站点下建立一个目录,把要发布的软件copy到目录下,客户端升级程序会在其工作目录创建一个跟服务器目录结构相同的文件夹结构,并下载各文件夹下的文件。

扩展与加强
当然一个完整的更新程序还有很多地方需要做,比方多版本管理、客户端有嵌入数据库时不应该覆盖,自动生成桌面快捷方式,注册启动项目等,但是对我来说,只要能下载就减少我80%工作量了,剩下的直接人肉搞定,作为上了年纪的程序员,尽量避免做折磨前列腺、颈椎、腰椎这些折寿的事情。

代码部分
升级站点跟扫描的WebService放在一起,分离打包上来太麻烦了,所以就把主要文件copy上来,相信你化个10几分钟就能把项目建立会来。

1.服务端部分

View Code

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace AppSyncCEClient
{
using AppSync;
using System.Reflection;
using System.Collections;
using System.IO;
using System.Net;
using System.Threading;
using System.Diagnostics;

public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
private AppSyncTask TaskMgr = null;
private void frmMain_Load(object sender, EventArgs e)
{

timer1.Enabled = false;
btnClose.Enabled = false;
lblTip.Text = "程序启动中,请稍等...";
this.Show();
Application.DoEvents();

ServiceAppSync service = new AppSync.ServiceAppSync();
service.Url = ConfigMgr.GetSetting("SyncUrl", "");

string version = ConfigMgr.GetSetting("Version", "0.0");
TaskMgr = new AppSyncTask(service, version,this);
TaskMgr.Do();

timer1.Enabled = true;

}

private void btnClose_Click(object sender, EventArgs e)
{
try
{
this.Enabled = false;
ProcessStartInfo psInfo = new ProcessStartInfo();
psInfo.FileName = Path.Combine(ConfigMgr._Path, ConfigMgr.GetSetting("StartPath", ""));
psInfo.UseShellExecute = true;

Process.Start(psInfo);
Thread.Sleep(1000);
}
catch { }
finally { this.Close(); }
}

private void timer1_Tick(object sender, EventArgs e)
{
if (TaskMgr.IsComplete)
{
btnClose.Enabled = true;
timer1.Enabled = false;
}
}

private void frmMain_Closing(object sender, CancelEventArgs e)
{
if (!TaskMgr.IsComplete)
{
MessageBox.Show("任务执行期间不允许关闭窗体!");
e.Cancel = true;
}
}
}

public delegate void ShowProcessMsgHandle(int progress,string msg);
/// <summary>
/// 同步任务
/// </summary>
public class AppSyncTask
{
Thread WorkerThread = null;

private AppSync.ServiceAppSync Service = null;
private string LocalVersion = string.Empty;
public string Version = string.Empty;
private frmMain UI = null;
private bool IsRun = false;
public AppSyncTask( ServiceAppSync service, string curVersion,frmMain form)
{

Service = service;
LocalVersion = curVersion;
UI = form;

}

public void Report(int progress, string msg)
{
if (UI.InvokeRequired)
{
UI.Invoke(new ShowProcessMsgHandle(Report), progress, msg);

}
else
{
UI.progressBar.Value = progress;
UI.lblTip.Text = msg;
}
}

public void Do()
{
try
{
IsRun = true;
WorkerThread = new Thread(InternalDo);
WorkerThread.Start();
Thread.Sleep(100);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

}
public bool IsComplete
{
get
{
return !IsRun;
}
}
private void InternalDo()
{
//计数器
int success = 0;
int error = 0;
int b = 0;
int t = 0;

try
{
#region
Report(0, "检测程序是否有可用更新....");
string version = Service.GetVersion();
Version = version;
if (string.Compare(LocalVersion, version, true) >= 0)
{
Report(100, "当前版本已经是最新版本");
IsRun = false;
return;
}
Report(5, "获取更新列表");
List<AppSyncItem> list = new List<AppSyncItem>(Service.GetList());

string msg = string.Format("有{0}个文件需要更新", list.Count);
Report(10, msg);

//创建本地目录
string root = ConfigMgr._Path;

List<AppSyncItem> dirList = list.FindAll(FilterDir);
dirList.Sort(CompareDir);
foreach (AppSyncItem dir in dirList)
{
string path = Path.Combine(root, dir.FileName);
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
}

List<AppSyncItem> downList = list.FindAll(FilterFile);
//更新文件
success = 0;
error = 0;
b = 90;
t = downList.Count;

#region  遍历下载文件
foreach (AppSyncItem file in downList)
{
try
{
string filename = Path.Combine(root, file.FileName);
//根据文件大小使用不同的下载方式
FileReadData response = Service.GetFileData(file.FileName);

if (response.Code == 0)
{
byte[] data = Convert.FromBase64String(response.DataB64);
using (FileStream fs = File.OpenWrite(filename))
{
fs.Position = 0;
fs.Write(data, 0, data.Length);
fs.Flush();
fs.Close();
}
success++;

msg = string.Format("{0}", file.FileName.Trim());
Report(funcPercent(success, error, t, b), msg);
}
else
{
error++;
msg = string.Format("下载{0}错误,{1}", file.FileName, response.Msg);
Report(funcPercent(success, error, t, b), msg);
}

}
catch (System.Net.WebException)
{
error++;
throw;
}
catch (Exception ex)
{
error++;
msg = string.Format(ex.Message, file.FileName);
Report(funcPercent(success, error, t, b), msg);
continue;
}

}
#endregion

msg = string.Format("更新结束,成功{0},失败{1}.", success, error);
Report(100, msg);
if (error == 0)
{
ConfigMgr.SetSetting("Version", Version);
ConfigMgr.SaveConfig();
}
Thread.Sleep(100);
IsRun = false;
#endregion
}
catch (Exception ex)
{
Report(funcPercent(success, error, t, b), ex.Message);
IsRun = false;

}

}
#region 委托
/// <summary>
/// 计算完成百分比
/// </summary>
/// <param name="s">成功数</param>
/// <param name="e">失败数</param>
/// <param name="t">总数</param>
/// <param name="b">基准百分比</param>
/// <returns></returns>
private int funcPercent(int s, int e, int t, int b)
{
if (t == 0) return 0;
return (int)((decimal)(e + s) * b / (decimal)t);
}
/// <summary>
/// 过滤目录
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
private bool FilterDir(AppSyncItem item)
{
return item.IsDir;
}
private bool FilterFile(AppSyncItem item)
{
return !item.IsDir;
}
private int CompareDir(AppSyncItem x, AppSyncItem y)
{
return x.FileName.Length - y.FileName.Length;
}
#endregion
}
public class ReportInfo
{
public string Msg = string.Empty;
}

}


另外关于vs2005 + wince 的一些注意,可以看下这里/article/4890186.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐