对于C#winform开发者来说,软件自动升级功能是一个很重要的功能。作者根据自身经验,和大家分享一下软件升级的实现方式。
注意:本文主要介绍通过WebService升级软件。作者的另一篇通过FTP方式升级软件的介绍可在作者的另一篇文中查看https://jingyan.baidu.com/article/4dc4084842d8fec8d946f1ca.html。
第一步:首先建立一个Winform程序,这里叫做AppUpdatePC.在Form1的.cs文件中复制一下代码:这里通过读取主程序的文件版本和升级包里面的升级程序的文件版本做匹配,来进行升级判断。如果两者程序版本一致,则进行升级,如果不一致,则不升级
string url = " http://XXX(服务器地址)/update/pcapp/";这里改为你的WebService地址。
string fUpdate = @"";
string AppName = "BarcodePrint";
string m_workPath = "";
string xmlFile = null;
public Form1()
{
InitializeComponent();
//m_workPath = Assembly.GetExecutingAssembly().GetName().CodeBase.Substring(0, Assembly.GetExecutingAssembly().GetName().CodeBase.LastIndexOf(@"/") + 1).Replace(@"file:///", "");
//Release版本
//m_workPath = System.IO.Path.GetFullPath(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
//m_workPath = System.IO.Path.GetDirectoryName(m_workPath);
m_workPath = AppDomain.CurrentDomain.BaseDirectory;
//m_workPath = Application.StartupPath;
//xmlFile = m_workPath;
//MessageBox.Show(m_workPath);
//string workPath = System.IO.Path.Combine(filePath, "Config.xml");
//DataSet ds = new DataSet();
//ds.ReadXml( m_workPath + "config.xml");
//url = ds.Tables[0].Rows[0]["WebServiceURL"].ToString();
//url = url.Substring(0, url.IndexOf("Service"));
//url += "update/Update_TKE_HT/";
//AppName = ds.Tables[0].Rows[0]["AppName"].ToString();
}
private void button1_Click(object sender, EventArgs e)
{
Download();
}
private void Download()
{
//获取本地应用程序目录
DirectoryInfo theFolder = new DirectoryInfo(Path.GetDirectoryName(this.m_workPath + "\\"));
//获取服务器目录
//DirectoryInfo theFolder = new DirectoryInfo(fUpdate);
try
{
this.button1.Enabled = false;
this.button2.Enabled = false;
this.Refresh();
foreach (FileInfo theFile in theFolder.GetFiles())
{
DownloadFile(theFile.Name, url + theFile.Name);
}
}
catch (Exception ex)
{
//MessageBox.Show(ex.Message);
}
finally
{
this.button1.Enabled = true;
this.button2.Enabled = true;
}
//启动程序
System.Diagnostics.Process.Start(this.m_workPath + "\\" + AppName + ".exe", "");
Application.Exit();
Close();
}
private void DownloadFile(string FileName, string strUrl)
{
HttpWebRequest request;
HttpWebResponse response = null;
try
{
System.Globalization.DateTimeFormatInfo dfi = null;
System.Globalization.CultureInfo ci = null;
ci = new System.Globalization.CultureInfo("zh-CN");
dfi = new System.Globalization.DateTimeFormatInfo();
//WebRequest wr = WebRequest.Create("");
//System.Net.WebResponse w=wr.
DateTime fileDate;
long totalBytes;
DirectoryInfo theFolder = new DirectoryInfo(Path.GetTempPath() + "");
string fileName = theFolder + FileName;
request = (HttpWebRequest)HttpWebRequest.Create(strUrl);
response = (HttpWebResponse)request.GetResponse();
if (response == null)
return;
fileDate = response.LastModified;
//if (File.GetLastWriteTime(m_workPath+"\\"+FileName) >= fileDate)
//{
// response.Close();
// return;
//}
totalBytes = response.ContentLength;
progressBar1.Maximum = Convert.ToInt32(totalBytes);
Stream stream = response.GetResponseStream();
FileStream sw = new FileStream(fileName, FileMode.Create);
int totalDownloadedByte = 0;
Byte[] @by = new byte[1024];
int osize = stream.Read(@by, 0, @by.Length);
while (osize > 0)
{
totalDownloadedByte = osize + totalDownloadedByte;
Application.DoEvents();
sw.Write(@by, 0, osize);
progressBar1.Value = totalDownloadedByte;
osize = stream.Read(@by, 0, @by.Length);
}
sw.Close();
stream.Close();
//System.Diagnostics.Process[] proc = System.Diagnostics.Process.GetProcessesByName(AppName);
////关闭原有应用程序的所有进程
//foreach (System.Diagnostics.Process pro in proc)
//{
// pro.Kill();
//}
//DirectoryInfo theFolder = new DirectoryInfo(Path.GetTempPath() + "ysy");
if (theFolder.Exists)
{
foreach (FileInfo theFile in theFolder.GetFiles())
{
//如果临时文件夹下存在与应用程序所在目录下的文件同名的文件,则删除应用程序目录下的文件
if (File.Exists(this.m_workPath + "\\" + Path.GetFileName(theFile.FullName)))
{
File.Delete(this.m_workPath + "\\" + Path.GetFileName(theFile.FullName));
//将临时文件夹的文件移到应用程序所在的目录下
File.Move(theFile.FullName, this.m_workPath + "\\" + Path.GetFileName(theFile.FullName));
}
}
}
//File.SetLastWriteTime(FileName, fileDate);
}
catch (Exception)
{
if (response != null)
response.Close();
//MessageBox.Show(ex.Message);
}
}
private void button2_Click(object sender, EventArgs e)
{
//System.Diagnostics.Process.Start(this.m_workPath + "\\" + AppName + ".exe");
this.Close();
}
private void Form1_Load(object sender, EventArgs e)
{
//Download();
}
public int setConfig(string pro, string par, string val)
{
XmlDocument xd = new XmlDocument();
xd.Load(xmlFile);
try
{
xd.FirstChild.SelectSingleNode(pro).SelectSingleNode(par).InnerText = val;
xd.Save(xmlFile);
xd = null;
return 0;
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
}
public int setParConfig(string ItemName, string ItemValue)
{
XmlDocument xd = new XmlDocument();
xd.Load(xmlFile);
try
{
xd.FirstChild.SelectSingleNode(ItemName).InnerText = ItemValue;
xd.Save(xmlFile);
xd = null;
return 0;
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
}
public string getConfig(string pro, string par)
{
XmlDocument xd = new XmlDocument();
xd.Load(xmlFile);
try
{
string str = xd.FirstChild.SelectSingleNode(pro).SelectSingleNode(par).InnerText;
xd = null;
return str;
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
}
private string GetVersion()
{
string version = "";
try
{
string strVersionPath = this.m_workPath + "version.txt";
StreamReader sw = new StreamReader( strVersionPath );
version = sw.ReadLine();
}
catch ( Exception ex)
{
MessageBox.Show(ex.Message);
}
return version;
}
private void Form1_Shown(object sender, EventArgs e)
{
Download();
}
}
第二步:在系统登录时,进行系统的版本号判断。这里写一个判断版本号是否一致的方法,来进行版本号的匹配,该代码写在WebService的实现代码中,中间的调用过程,大家可根据自己的项目自身情况,进行调用代码的编写。判断版本号一致的代码如下:
public static bool VerifyVersion(string[] FileVersion, string[] FileName)
{
LogNote ln = null;
try
{
string strVersion = null;
ln = new LogNote(AppDomain.CurrentDomain.BaseDirectory + "barcode.log");
for (int i = 0; i < FileName.Length; i++)
{
FileVersionInfo fv = FileVersionInfo.GetVersionInfo(AppDomain.CurrentDomain.BaseDirectory + "\\update\\" + FileName[i]);
strVersion = fv.FileVersion;
//strVersion = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory+"\\update\\" + FileName[i]).GetName().Version.ToString();
//Version v = new Version("");
ln.Write(i.ToString(), FileVersion + "/" + strVersion);
if (FileVersion[i] != strVersion)
{
return false;
}
}
return true;
}
catch (Exception er)
{
return true;
}
}
WebService声明的代码如下:
[WebMethod]
public bool verfiyVersion(string[] Version, string[] FileName)
{
return CommonDA.VerifyVersion(Version, FileName);
}
WInform程序的接口实现代码如下:
public bool verifyVersion(string[] Version, string[] FileName)
{
Common co = Common.GetCommon();
return co.m_service.verfiyVersion(Version, FileName);
}
winform程序的函数调用代码如下所示:
string[] fileName = new string[2];
string[] fileVersion = new string[2];
fileName[0] = "\\htapp\\HTApp.exe";程序路径
fileVersion[0] = this.labversion.Text;
//fileName[1] = "U8Business.dll";
//fileVersion[1] = this.labDllversion.Text;
if (!Common.CurrentUser.verifyVersion(fileVersion, fileName))
{
MessageBox.Show("程序有新的版本,请确定后更新!");
System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName
(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).ToString() + "\\AppUpdate.exe", "123");
Application.Exit();
Close();
return;
}
第三步:修改程序版本号,完成升级包的制作。打开主程序项目的目录,点击“propertiey”,打开AssmsblyInfo类,修改版本号的信息,如下所示,修改之后保存,重新生成程序,然后就可以把Bin/Debug目录下的新程序放到WebService的相对应的更新目录下。带程序启动时,会自动监测程序的版本号,并且进行升级。
// 程序集的版本信息由下面四个值组成:
//
// 主版本
// 次版本
// 内部版本号
// 修订号
//
// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.2.2")]
[assembly: AssemblyFileVersion("1.2.2.2")]