基于C/S的开发有开发效率高,对于业务逻辑复杂,且不需要外网使用具有较大优势,但是弊端也不可忽视,就是升级麻烦,,所以对于版本自动升级就显得必不可少,废话到此为止,下面直接上硬货。
1.逻辑就是利用webapi将更新的文件下载下来ZIP格式。
2.主程序运行时,先将本机的的版本号与webapi的所对应的版本号对比,不一致是,将主程序停止,激活updata的程序,实现下载,解压,替换。完成重新启动主程序
- WebApi,写两个接口
1.检测版本
2.更新软件
新建WebApi,修改App_Start–RouteConfig.cs
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home",
action = "Index", id = UrlParameter.Optional }
);
在control---ValuesController.cs 写两个方法
//读取指定xml文件的版本号,你也可以直接返回一个string,不一定要xml。
public string GetVersion()
{
XmlDocument xmlDoc = new XmlDocument();
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
//加载同目录下的UpdateXMl.xml文件
xmlDoc.Load(baseDirectory + @"//UpdateXMl.xml");
XmlNode xmlNode = xmlDoc.SelectNodes("Update/Soft")[0];
string Verson = xmlNode.SelectSingleNode("Verson").InnerText;
return Verson;
}
//将新版本的winfrom文件打包成ZIP文件,放到//Resource,下面,没有Resource,自己新建文件夹
[HttpGet]//因为是直接下载文件,此注释不能少
public HttpResponseMessage DownFile()
{
string FilePath = AppDomain.CurrentDomain.BaseDirectory + @"//Resource//Debug.zip";//获得运行文件的根目录
FileStream stream = new FileStream(FilePath, FileMode.Open);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = HttpUtility.UrlEncode(Path.GetFileName(FilePath))
};
return response;
}
Rescoce是存放最新的ZIP的文件,UPDATE.xml是存放最新的版本号的
以下是XML文件
<?xml version="1.0" encoding="utf-8" ?>
<Update>
<Soft Name="BlogWriter">
<Verson>1.0.0.5</Verson>
<DownLoad>代写网址</DownLoad>
</Soft>
</Update>
webapi就写完了,直接发布到IIS中,值得注意的是,IIS发布后要将目录浏览打开
在网页中测试一下这两个接口是否OK
以下是写winfrom的程序
在winfrom中解决方案中写两个方案,一个是主程序–PC,一个是升级的程序–autoUpdate
先写升级程序—autoUpdate:
//程序激活的时候直接运行下载和更新主程序的文件
private void Form1_Load(object sender, EventArgs e)
{
//common方法的实现在下方
Common.DownFile(); //下载更新的文件
//Application.StartupPath获得程序运行的文件夹
string dirEcgPath = Application.StartupPath + "\\" + "autoupload";
if (!Directory.Exists(dirEcgPath)) Directory.CreateDirectory(dirEcgPath);
//解压文件
Common.Unzip();
try
{
//将解压的文件,复制替换主程序的文件
DirectoryInfo TheFolder = new DirectoryInfo(dirEcgPath);
//循环文件的夹
foreach (FileInfo NextFile in TheFolder.GetFiles())
{
//找到主程序的文件夹,按照自己的程序的路径找
File.Copy(NextFile.FullName, Application.StartupPath.Replace("autoUpdate\\bin","AppUpdatePC\\bin" )+"\\" + NextFile.Name, true);
}
}
catch(Exception)
{
MessageBox.Show("请关闭系统在执行更新操作!");
Application.Exit();
}
MessageBox.Show("已经更新完成,请重新启动程序");
}
下面是Common的方法
//下载文件
public static void DownFile()
{
try
{
WebClient wc = new WebClient();
wc.DownloadFile(new Uri("http://localhost:8989/Values/DownFile"), "Update.zip");
}
catch (Exception e)
{
throw e;
}
}
//解压文件,nuget用的是SharpZip
public static void Unzip()
{
//找到下载的ZIP的文件,
string filePath = AppDomain.CurrentDomain.BaseDirectory + "Update.zip";
ZipInputStream stream = new ZipInputStream(File.OpenRead(filePath));
ZipEntry theEntry = null;
//解压后的文件存放的路径
string directory = AppDomain.CurrentDomain.BaseDirectory+ "autoupload";
while ((theEntry = stream.GetNextEntry()) != null)
{
string directoryName = Path.GetDirectoryName(theEntry.Name);
string fileName = Path.GetFileName(theEntry.Name);
if (directoryName != string.Empty)
Directory.CreateDirectory(directory + directoryName);
if (fileName != string.Empty)
{
FileStream streamWriter = File.Create(Path.Combine(directory, theEntry.Name));
int size = 2048;
byte[] data = new byte[size];
while (true)
{
size = stream.Read(data, 0, data.Length);
if (size > 0)
streamWriter.Write(data, 0, size);
else
break;
}
streamWriter.Close();
}
}
stream.Close();
//将压缩包删除
File.Delete(filePath);
}
接下来写主程序,在Promgram.cs在程序运行时直接检测,当然你也可以写方法,调用
static void Main()
{
//开始检测是否需要更新
if (checkUpdateLoad())
{
//如果需要更新,主程序退出,那么此时的autoUpdate.exe已经在运行了
Application.Exit();
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
public static bool checkUpdateLoad()
{
bool b = false;
//利用WebApi获得最新的版本的API,获取webapi上版本号,可以写方法,偷懒了
string baseUrl = "http://localhost:8989";
string serviceUrl = string.Format("{0}/{1}", baseUrl, "Values/GetVersion");
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(serviceUrl);
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
string returnXml = reader.ReadToEnd();
reader.Close();
myResponse.Close();
//这边检测webapi返回的一下returnXml 是什么,我这边返回的数据多了几个符号,下面我处理了。
returnXml = returnXml.Substring(1, returnXml.Length-2);
//以下获得主程序的版本号 这边读取的是Properties下面的AssemblyInfo.cs
//loadFile指的是你程序文件位置
string verson = Assembly.LoadFrom(loadFile).GetName().Version.ToString();
if(!returnXml.Equals(verson)&& MessageBox.Show("检查到新版本,是否更新?", "版本检查", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
//找到autoUpdate的程序的路径,我这边是,加工处理了,你可以根据自己的需求修改
string path = Application.StartupPath.Replace("AppUpdatePC\\bin", "autoUpdate\\bin");
//获得本机的进程,将autoUpdate.exe,并且运行,利用本机的进程运行autoUpdate.exe.
Process process = new Process();
process.StartInfo.FileName = "autoUpdate.exe";
process.StartInfo.WorkingDirectory = path;
process.StartInfo.CreateNoWindow = true;
//开始运行
process.Start();
b = true;
}
return b;
}
如果主程序更新了,将debug文件夹下的程序,打包成zip文件,SharpZip只支持zip,不要打包成rar,楼主踩坑了。
以上自动更新的程序就算完成了。没有实现进度条。后期改进