Winform(C#.NET)自动更新组件的使用及部分功能实现
声明:核心功能的实现是由园子里圣殿骑士大哥写的,本人是基于他核心代码,按照自己需求进行修改的。
而AutoUpdaterService.xml文件生成工具是基于评论#215楼 ptangbao的代码而改写的。
由于这个组件是在10年写的,.net也有更新有的方法已提示过时,更改如下:
//Added the function to support proxy
//clientDownload.Proxy = System.Net.WebProxy.GetDefaultProxy();
clientDownload.Proxy = WebRequest.GetSystemWebProxy();
更改的主要功能如下:
1》如果有更新将会直接更新,不再提供由用户点击确定后再更新。(强制更新)(这个暂时没有整理出来,后续会整理出来)
2》更新前判断主程序进程是否开启:
如果有更新,主程序开启,关闭主程序,更新完成后自动启动主程序。
如果没有更新,直接启动主程序。
3》不再根据版本号不同进行更新。
圣殿骑士大哥的是根据版本号,当然这也是最正规的,可是我们的程序有点特殊,所以不再根据版本号控制,而是根据GUID。
这样就是有一点好处不管版本号一不一样,只要GUID不一样就是要更新。
比如文件夹如下:
使用CreateXmlTools.exe工具生成xml文件,增加的节点属性有version,值时GUID
<?xml version="1.0" encoding="utf-8"?>
<updateFiles>
<file path="AutoUpdater.dll" url="http://172.30.100.55:8011/AutoUpdater.dll" lastver="5.0.0.0" size="26624" needRestart="false" version="1ef2b9dc-d14f-4fc4-a5ec-bdb07a6ba98c" />
<file path="ReadMe.dll" url="http://172.30.100.55:8011/ReadMe.dll" lastver="" size="472" needRestart="false" version="3ddc1926-3088-468f-9088-92b07156c757" />
<file path="aspnet_client/ReadMe.dll" url="http://172.30.100.55:8011/aspnet_client/ReadMe.dll" lastver="" size="472" needRestart="false" version="4aaa87e2-63bd-486a-9957-1c2df21607cb" />
</updateFiles>
version就是用来替代lastver的,只要不一样就更新
4》客户端更新主程序更改autoupdater.config文件的更新方式
config里不必包含所有文件的配置,只要求配置成如下:
<?xml version="1.0" encoding="utf-8" ?>
<Config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Enabled>true</Enabled>
<ServerUrl>http://172.30.100.55:8011/AutoupdateService.xml</ServerUrl>
<UpdateFileList> </UpdateFileList>
</Config>
ServerUrl就是web服务器的地址加上面生成xml文件的地址。
更新完成后客户端会自动更新autoupdater.config文件,将本地的guid保持与服务端一致,再次点击guid一致的不再更新
以上是大致改动的地方。
下面来说说代码吧:
由于增加了GUID这块,所以RemoteFile、LocalFile和DownloadFileInfo三个实体类都应该增加一个字段和一个属性
LocalFile.cs
public class LocalFile
{
#region The private fields
private string path = "";
private string lastver = "";
private int size = ;
private string version = "";
#endregion #region The public property
[XmlAttribute("path")]
public string Path { get { return path; } set { path = value; } }
[XmlAttribute("lastver")]
public string LastVer { get { return lastver; } set { lastver = value; } }
[XmlAttribute("size")]
public int Size { get { return size; } set { size = value; } }
[XmlAttribute("version")]
public string Version { get { return version; } set { version = value; } }
#endregion #region The constructor of LocalFile
public LocalFile(string path, string ver, int size,string versionid)
{
this.path = path;
this.lastver = ver;
this.size = size;
this.version = versionid;
} public LocalFile()
{
}
#endregion }
RemoteFile.cs
public class RemoteFile
{
#region The private fields
private string path = "";
private string url = "";
private string lastver = "";
private int size = ;
private bool needRestart = false;
private string version = "";
#endregion #region The public property
public string Path { get { return path; } }
public string Url { get { return url; } }
public string LastVer { get { return lastver; } }
public int Size { get { return size; } }
public bool NeedRestart { get { return needRestart; } }
public string Verison { get { return version; } }
#endregion #region The constructor of AutoUpdater
public RemoteFile(XmlNode node)
{
this.path = node.Attributes["path"].Value;
this.url = node.Attributes["url"].Value;
this.lastver = node.Attributes["lastver"].Value;
this.size = Convert.ToInt32(node.Attributes["size"].Value);
this.needRestart = Convert.ToBoolean(node.Attributes["needRestart"].Value);
this.version = node.Attributes["version"].Value;
}
#endregion
}
DownloadFileInfo.cs
public class DownloadFileInfo
{
#region The private fields
string downloadUrl = string.Empty;
string fileName = string.Empty;
string lastver = string.Empty;
int size = ;
string version = string.Empty;
#endregion #region The public property
public string DownloadUrl { get { return downloadUrl; } }
public string FileFullName { get { return fileName; } }
public string FileName { get { return Path.GetFileName(FileFullName); } }
public string LastVer { get { return lastver; } set { lastver = value; } }
public int Size { get { return size; } }
public string Version { get { return version; } set { version = value; } }
#endregion #region The constructor of DownloadFileInfo
public DownloadFileInfo(string url, string name, string ver, int size,string versionid)
{
this.downloadUrl = url;
this.fileName = name;
this.lastver = ver;
this.size = size;
this.version = versionid;
}
#endregion
}
ConstFile.cs
一些常量配置文件
CommonUnitity.cs
//主要是更改获取多层目录文件夹路径
public static string GetFolderUrl(DownloadFileInfo file)
{
string folderPathUrl = string.Empty;
int folderPathPoint = file.DownloadUrl.IndexOf("/", ) + ;
string filepathstring = file.DownloadUrl.Substring(folderPathPoint);
//int folderPathPoint1 = filepathstring.IndexOf("/");
//string filepathstring1 = filepathstring.Substring(folderPathPoint1 + 1);
//if(filepathstring1.IndexOf("/") != -1)
if(filepathstring.IndexOf("/") != -)
{
//string[] ExeGroup = filepathstring1.Split('/');
string[] ExeGroup = filepathstring.Split('/');
for (int i = ; i < ExeGroup.Length - ; i++)
{
folderPathUrl += "\\" + ExeGroup[i];
}
if (!Directory.Exists(SystemBinUrl + ConstFile.TEMPFOLDERNAME + folderPathUrl))
{
Directory.CreateDirectory(SystemBinUrl + ConstFile.TEMPFOLDERNAME + folderPathUrl);
}
}
return folderPathUrl;
}
autoupdater.cs
public class AutoUpdater : IAutoUpdater
{
#region The private fields
private Config config = null;
private bool bNeedRestart = false;
private bool bDownload = false;
List<DownloadFileInfo> downloadFileListTemp = null;
#endregion #region The public event
public event ShowHandler OnShow;
#endregion #region The constructor of AutoUpdater
public AutoUpdater()
{
config = Config.LoadConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConstFile.FILENAME));
}
#endregion #region The public method
public void Update()
{
if (!config.Enabled)
return; Dictionary<string, RemoteFile> listRemotFile = ParseRemoteXml(config.ServerUrl);
List<DownloadFileInfo> downloadList = new List<DownloadFileInfo>(); foreach (LocalFile file in config.UpdateFileList)
{
if (listRemotFile.ContainsKey(file.Path))
{
RemoteFile rf = listRemotFile[file.Path];
//Version v1 = new Version(rf.LastVer);
//Version v2 = new Version(file.LastVer);
//if (v1 > v2)
string v1 = rf.Verison;
string v2 = file.Version;
if (v1 != v2)
{
downloadList.Add(new DownloadFileInfo(rf.Url, rf.Path, rf.LastVer, rf.Size, rf.Verison));
file.Path = rf.Path;
file.LastVer = rf.LastVer;
file.Size = rf.Size;
file.Version = rf.Verison;
if (rf.NeedRestart)
bNeedRestart = true; bDownload = true;
} listRemotFile.Remove(file.Path);
}
} foreach (RemoteFile file in listRemotFile.Values)
{
downloadList.Add(new DownloadFileInfo(file.Url, file.Path, file.LastVer, file.Size, file.Verison));
bDownload = true;
config.UpdateFileList.Add(new LocalFile(file.Path, file.LastVer, file.Size, file.Verison));
if (file.NeedRestart)
bNeedRestart = true;
} downloadFileListTemp = downloadList; if (bDownload)
{
OperProcess op = new OperProcess();
op.InitUpdateEnvironment();
DownloadConfirm dc = new DownloadConfirm(downloadList); if (this.OnShow != null)
this.OnShow();
StartDownload(downloadList);
}
} public void RollBack()
{
foreach (DownloadFileInfo file in downloadFileListTemp)
{
string tempUrlPath = CommonUnitity.GetFolderUrl(file);
string oldPath = string.Empty;
try
{
if (!string.IsNullOrEmpty(tempUrlPath))
{
oldPath = Path.Combine(CommonUnitity.SystemBinUrl + tempUrlPath.Substring(), file.FileName);
}
else
{
oldPath = Path.Combine(CommonUnitity.SystemBinUrl, file.FileName);
} if (oldPath.EndsWith("_"))
oldPath = oldPath.Substring(, oldPath.Length - ); MoveFolderToOld(oldPath + ".old", oldPath); }
catch (Exception ex)
{
//log the error message,you can use the application's log code
}
}
} #endregion #region The private method
string newfilepath = string.Empty;
private void MoveFolderToOld(string oldPath, string newPath)
{
if (File.Exists(oldPath) && File.Exists(newPath))
{
System.IO.File.Copy(oldPath, newPath, true);
}
} private void StartDownload(List<DownloadFileInfo> downloadList)
{
DownloadProgress dp = new DownloadProgress(downloadList);
if (dp.ShowDialog() == DialogResult.OK)
{
//
if (DialogResult.Cancel == dp.ShowDialog())
{
return;
}
//Update successfully
config.SaveConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConstFile.FILENAME)); if (bNeedRestart)
{
//Delete the temp folder
Directory.Delete(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConstFile.TEMPFOLDERNAME), true); MessageBox.Show(ConstFile.APPLYTHEUPDATE, ConstFile.MESSAGETITLE, MessageBoxButtons.OK, MessageBoxIcon.Information);
CommonUnitity.RestartApplication();
}
}
} private Dictionary<string, RemoteFile> ParseRemoteXml(string xml)
{
XmlDocument document = new XmlDocument();
document.Load(xml); Dictionary<string, RemoteFile> list = new Dictionary<string, RemoteFile>();
foreach (XmlNode node in document.DocumentElement.ChildNodes)
{
list.Add(node.Attributes["path"].Value, new RemoteFile(node));
} return list;
}
#endregion }
OperProcess.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics; namespace AutoUpdater
{
/// <summary>
/// 启动进程、关闭进程操作
/// </summary>
public class OperProcess
{
#region init update env
public void InitUpdateEnvironment()
{
if (IfExist("MainProgram"))
{
CloseExe("MainProgram");
}
}
#endregion init update env #region updated start process
public void StartProcess()
{
string path = System.Environment.CurrentDirectory;
if (!IfExist("MainProgram"))
{
StartExe(path, "MainProgram.exe");
}
CloseExe("KnightsWarrior");
} #endregion #region 启动进程、关闭进程、判断进程是否存在
//启动exe绝对路径
private void StartExe(string filePath, string fileName)
{
Process proc = new Process();
proc.StartInfo.UseShellExecute = true;//是否使用操作系统外壳程序启动进程 proc.StartInfo.WorkingDirectory = filePath;//启动进程的初始目录
proc.StartInfo.FileName = fileName;
proc.Start();
} //exeName 关闭的exe进程名
private void CloseExe(string exeName)
{
Process[] arrPro = Process.GetProcessesByName(exeName);
foreach (Process pro in arrPro)
pro.Kill();
}
//processName 进程名
private bool IfExist(string processName)
{
Process[] pro = Process.GetProcessesByName(processName);
return pro.Count() > ;
}
#endregion 启动进程、关闭进程
}
}
DownloadProgress.cs
public partial class DownloadProgress : Form
{
#region The private fields
private bool isFinished = false;
private List<DownloadFileInfo> downloadFileList = null;
private List<DownloadFileInfo> allFileList = null;
private ManualResetEvent evtDownload = null;
private ManualResetEvent evtPerDonwload = null;
private WebClient clientDownload = null;
#endregion #region The constructor of DownloadProgress
public DownloadProgress(List<DownloadFileInfo> downloadFileListTemp)
{
InitializeComponent(); this.downloadFileList = downloadFileListTemp;
allFileList = new List<DownloadFileInfo>();
foreach (DownloadFileInfo file in downloadFileListTemp)
{
allFileList.Add(file);
}
}
#endregion #region The method and event
private void OnFormClosing(object sender, FormClosingEventArgs e)
{
if (!isFinished && DialogResult.No == MessageBox.Show(ConstFile.CANCELORNOT, ConstFile.MESSAGETITLE, MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
e.Cancel = true;
return;
}
else
{
if (clientDownload != null)
clientDownload.CancelAsync(); evtDownload.Set();
evtPerDonwload.Set();
}
} private void OnFormLoad(object sender, EventArgs e)
{
evtDownload = new ManualResetEvent(true);
evtDownload.Reset();
ThreadPool.QueueUserWorkItem(new WaitCallback(this.ProcDownload));
} long total = ;
long nDownloadedTotal = ; private void ProcDownload(object o)
{
string tempFolderPath = Path.Combine(CommonUnitity.SystemBinUrl, ConstFile.TEMPFOLDERNAME);
if (!Directory.Exists(tempFolderPath))
{
Directory.CreateDirectory(tempFolderPath);
} evtPerDonwload = new ManualResetEvent(false); foreach (DownloadFileInfo file in this.downloadFileList)
{
total += file.Size;
}
try
{
while (!evtDownload.WaitOne(, false))
{
if (this.downloadFileList.Count == )
break; DownloadFileInfo file = this.downloadFileList[]; //Debug.WriteLine(String.Format("Start Download:{0}", file.FileName)); this.ShowCurrentDownloadFileName(file.FileName); //Download
clientDownload = new WebClient(); //Added the function to support proxy
//clientDownload.Proxy = System.Net.WebProxy.GetDefaultProxy();
clientDownload.Proxy = WebRequest.GetSystemWebProxy();
clientDownload.Proxy.Credentials = CredentialCache.DefaultCredentials;
clientDownload.Credentials = System.Net.CredentialCache.DefaultCredentials;
//End added clientDownload.DownloadProgressChanged += (object sender, DownloadProgressChangedEventArgs e) =>
{
try
{
this.SetProcessBar(e.ProgressPercentage, (int)((nDownloadedTotal + e.BytesReceived) * / total));
}
catch
{
//log the error message,you can use the application's log code
} }; clientDownload.DownloadFileCompleted += (object sender, AsyncCompletedEventArgs e) =>
{
try
{
DealWithDownloadErrors();
DownloadFileInfo dfile = e.UserState as DownloadFileInfo;
nDownloadedTotal += dfile.Size;
this.SetProcessBar(, (int)(nDownloadedTotal * / total));
evtPerDonwload.Set();
}
catch (Exception)
{
//log the error message,you can use the application's log code
} }; evtPerDonwload.Reset(); //Download the folder file
string tempFolderPath1 = CommonUnitity.GetFolderUrl(file);
if (!string.IsNullOrEmpty(tempFolderPath1))
{
tempFolderPath = Path.Combine(CommonUnitity.SystemBinUrl, ConstFile.TEMPFOLDERNAME);
tempFolderPath += tempFolderPath1;
}
else
{
tempFolderPath = Path.Combine(CommonUnitity.SystemBinUrl, ConstFile.TEMPFOLDERNAME);
} clientDownload.DownloadFileAsync(new Uri(file.DownloadUrl), Path.Combine(tempFolderPath, file.FileName), file);
//Wait for the download complete
evtPerDonwload.WaitOne(); clientDownload.Dispose();
clientDownload = null; //Remove the downloaded files
this.downloadFileList.Remove(file);
} }
catch (Exception)
{
ShowErrorAndRestartApplication();
//throw;
} //When the files have not downloaded,return.
if (downloadFileList.Count > )
{
return;
} //Test network and deal with errors if there have
DealWithDownloadErrors(); //Debug.WriteLine("All Downloaded");
foreach (DownloadFileInfo file in this.allFileList)
{
string tempUrlPath = CommonUnitity.GetFolderUrl(file);
string oldPath = string.Empty;
string newPath = string.Empty;
try
{
if (!string.IsNullOrEmpty(tempUrlPath))
{
oldPath = Path.Combine(CommonUnitity.SystemBinUrl + tempUrlPath.Substring(), file.FileName);
newPath = Path.Combine(CommonUnitity.SystemBinUrl + ConstFile.TEMPFOLDERNAME + tempUrlPath, file.FileName);
}
else
{
oldPath = Path.Combine(CommonUnitity.SystemBinUrl, file.FileName);
newPath = Path.Combine(CommonUnitity.SystemBinUrl + ConstFile.TEMPFOLDERNAME, file.FileName);
} //just deal with the problem which the files EndsWith xml can not download
System.IO.FileInfo f = new FileInfo(newPath);
if (!file.Size.ToString().Equals(f.Length.ToString()) && !file.FileName.ToString().EndsWith(".xml"))
{
ShowErrorAndRestartApplication();
} //Added for dealing with the config file download errors
string newfilepath = string.Empty;
if (newPath.Substring(newPath.LastIndexOf(".") + ).Equals(ConstFile.CONFIGFILEKEY))
{
if (System.IO.File.Exists(newPath))
{
if (newPath.EndsWith("_"))
{
newfilepath = newPath;
newPath = newPath.Substring(, newPath.Length - );
oldPath = oldPath.Substring(, oldPath.Length - );
}
File.Move(newfilepath, newPath);
}
}
//End added if (File.Exists(oldPath))
{
MoveFolderToOld(oldPath, newPath);
}
else
{
//Edit for config_ file
if (!string.IsNullOrEmpty(tempUrlPath))
{
if (!Directory.Exists(CommonUnitity.SystemBinUrl + tempUrlPath.Substring()))
{
Directory.CreateDirectory(CommonUnitity.SystemBinUrl + tempUrlPath.Substring()); MoveFolderToOld(oldPath, newPath);
}
else
{
MoveFolderToOld(oldPath, newPath);
}
}
else
{
MoveFolderToOld(oldPath, newPath);
} }
}
catch (Exception exp)
{
//log the error message,you can use the application's log code
} } //After dealed with all files, clear the data
this.allFileList.Clear(); if (this.downloadFileList.Count == )
Exit(true);
else
Exit(false); evtDownload.Set();
} //To delete or move to old files
void MoveFolderToOld(string oldPath, string newPath)
{
if (File.Exists(oldPath + ".old"))
File.Delete(oldPath + ".old"); if (File.Exists(oldPath))
File.Move(oldPath, oldPath + ".old"); File.Move(newPath, oldPath);
//File.Delete(oldPath + ".old");
} delegate void ShowCurrentDownloadFileNameCallBack(string name);
private void ShowCurrentDownloadFileName(string name)
{
if (this.labelCurrentItem.InvokeRequired)
{
ShowCurrentDownloadFileNameCallBack cb = new ShowCurrentDownloadFileNameCallBack(ShowCurrentDownloadFileName);
this.Invoke(cb, new object[] { name });
}
else
{
this.labelCurrentItem.Text = name;
}
} delegate void SetProcessBarCallBack(int current, int total);
private void SetProcessBar(int current, int total)
{
if (this.progressBarCurrent.InvokeRequired)
{
SetProcessBarCallBack cb = new SetProcessBarCallBack(SetProcessBar);
this.Invoke(cb, new object[] { current, total });
}
else
{
this.progressBarCurrent.Value = current;
this.progressBarTotal.Value = total;
}
} delegate void ExitCallBack(bool success);
private void Exit(bool success)
{
if (this.InvokeRequired)
{
ExitCallBack cb = new ExitCallBack(Exit);
this.Invoke(cb, new object[] { success });
}
else
{
this.isFinished = success;
this.DialogResult = success ? DialogResult.OK : DialogResult.Cancel;
this.Close();
}
} private void OnCancel(object sender, EventArgs e)
{
//bCancel = true;
//evtDownload.Set();
//evtPerDonwload.Set();
ShowErrorAndRestartApplication();
} private void DealWithDownloadErrors()
{
try
{
//Test Network is OK or not.
Config config = Config.LoadConfig(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ConstFile.FILENAME));
WebClient client = new WebClient();
client.DownloadString(config.ServerUrl);
}
catch (Exception)
{
//log the error message,you can use the application's log code
ShowErrorAndRestartApplication();
}
} private void ShowErrorAndRestartApplication()
{
MessageBox.Show(ConstFile.NOTNETWORK,ConstFile.MESSAGETITLE, MessageBoxButtons.OK, MessageBoxIcon.Information);
CommonUnitity.RestartApplication();
} #endregion
}
以上就是整体的自动更新程序核心代码。
下面是创建xml的程序代码:
代码是根据评论修改的如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.IO;
using System.Diagnostics; namespace CreateXmlTools
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
txtWebUrl.Text = "172.30.100.55:8011";
txtWebUrl.ForeColor = Color.Gray;
} //获取当前目录
//string currentDirectory = AppDomain.CurrentDomain.BaseDirectory;
string currentDirectory = System.Environment.CurrentDirectory;
//服务端xml文件名称
string serverXmlName = "AutoupdateService.xml";
//更新文件URL前缀
string url = string.Empty; void CreateXml()
{
//创建文档对象
XmlDocument doc = new XmlDocument();
//创建根节点
XmlElement root = doc.CreateElement("updateFiles");
//头声明
XmlDeclaration xmldecl = doc.CreateXmlDeclaration("1.0", "utf-8", null);
doc.AppendChild(xmldecl);
DirectoryInfo dicInfo = new DirectoryInfo(currentDirectory); //调用递归方法组装xml文件
PopuAllDirectory(doc, root, dicInfo);
//追加节点
doc.AppendChild(root);
//保存文档
doc.Save(serverXmlName);
} //递归组装xml文件方法
private void PopuAllDirectory(XmlDocument doc, XmlElement root, DirectoryInfo dicInfo)
{
foreach (FileInfo f in dicInfo.GetFiles())
{
//排除当前目录中生成xml文件的工具文件
if (f.Name != "CreateXmlTools.exe" && f.Name != "AutoupdateService.xml")
{
string path = dicInfo.FullName.Replace(currentDirectory, "").Replace("\\", "/");
string folderPath=string.Empty;
if (path != string.Empty)
{
folderPath = path.TrimStart('/') + "/";
}
XmlElement child = doc.CreateElement("file");
child.SetAttribute("path", folderPath + f.Name);
child.SetAttribute("url", url + path + "/" + f.Name);
child.SetAttribute("lastver", FileVersionInfo.GetVersionInfo(f.FullName).FileVersion);
child.SetAttribute("size", f.Length.ToString());
child.SetAttribute("needRestart", "false");
child.SetAttribute("version", Guid.NewGuid().ToString());
root.AppendChild(child);
}
} foreach (DirectoryInfo di in dicInfo.GetDirectories())
PopuAllDirectory(doc, root, di);
} private void btnCreate_Click(object sender, EventArgs e)
{
url = "http://" + txtWebUrl.Text.Trim();
CreateXml();
ReadXml();
} private void ReadXml()
{
string path="AutoupdateService.xml";
rtbXml.ReadOnly = true;
if (File.Exists(path))
{
rtbXml.Text = File.ReadAllText(path);
}
} private void txtWebUrl_Enter(object sender, EventArgs e)
{
txtWebUrl.ForeColor = Color.Black;
if (txtWebUrl.Text.Trim() == "172.30.100.55:8011")
{
txtWebUrl.Text = string.Empty;
}
} }
}
由于我的主程序是被别人写死的(没有修改权限没有代码)所以我只能单独写更新程序,由用户打开我的更新程序调用exe的方式来处理
所以多了一个程序专门用来更新的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AutoUpdater;
using System.Net;
using System.Xml;
using KnightsWarriorAutoupdater; namespace KnightsWarrior
{
public partial class UpdateForm : Form
{
public UpdateForm()
{
InitializeComponent();
InitCheckUpdate();
}
void InitCheckUpdate()
{
#region check and download new version program
bool bHasError = false;
IAutoUpdater autoUpdater = new KnightsWarriorAutoupdater.AutoUpdater();
try
{
autoUpdater.Update();
}
catch (WebException exp)
{
MessageBox.Show("服务器连接失败");
bHasError = true;
}
catch (XmlException exp)
{
bHasError = true;
MessageBox.Show("下载更新文件错误");
}
catch (NotSupportedException exp)
{
bHasError = true;
MessageBox.Show("升级文件配置错误");
}
catch (ArgumentException exp)
{
bHasError = true;
MessageBox.Show("下载升级文件错误");
}
catch (Exception exp)
{
bHasError = true;
MessageBox.Show("更新过程中出现错误");
}
finally
{
if (bHasError == true)
{
try
{
autoUpdater.RollBack();
}
catch (Exception)
{
//Log the message to your file or database
}
}
OperProcess op = new OperProcess();
//启动进程
op.StartProcess();
}
#endregion
}
}
}
1、服务器端
1、CreateXmlTools.exe给发布dll人员使用,用来生成要升级文件的列表,放在更新文件中的。
2、webServer地址是web服务器的地址。
3、点击生成之后会生成一个文件名为AutoupdateService.xml文件。
4、将生成的xml文件放置在web服务器的根目录里。
2、客户端
1、AutoUpdater.Config,该文件是保证客户端更新程序调用获取更新文件列表时使用的。
2、KnightsWarrior.exe更新主程序,用户直接调用该文件
3、AutoUpdater.dll更新程序的核心程序
本程序是要结合web服务器使用的,所有要更新的文件需要放在搭建的web服务器上,按照对应的目录存放,点CreateXmlTools.exe会生成一个xml文件的。
以上就是所有修改和增加部分的程序的代码及一些简要说明。建议先去看看组件源码,圣殿骑士大哥将其托管在托管地址。欢迎拍砖!
具体的使用方式和强制更新的代码在:Winform(C#.NET)自动更新组件的使用及部分功能实现(续),Demo也在这里。
Winform(C#.NET)自动更新组件的使用及部分功能实现的更多相关文章
- Winform(C#.NET)自动更新组件的使用及部分功能实现(一点改进功能)
接前两篇继续: Winform(C#.NET)自动更新组件的使用及部分功能实现 Winform(C#.NET)自动更新组件的使用及部分功能实现(续) 借鉴文章:http://www.cnblogs.c ...
- Winform(C#.NET)自动更新组件的使用及部分功能实现(续)
接昨天的文章Winform(C#.NET)自动更新组件的使用及部分功能实现 强制更新的实现部分: 将DownloadConfirm窗体修改成单纯的类 public class DownloadConf ...
- Winform自动更新组件分享
作者:圣殿骑士 出处:http://www.cnblogs.com/KnightsWarrior/ 关于作者:专注于微软平台项目架构.管理和企业解决方案.自认在面向对象及面向服务领域有一定的造诣,熟悉 ...
- 【Android】友盟的自动更新组件
前言 又好又专业的服务能帮开发者省很多时间.一开始做项目也准备自己来统计数据.自己做自动更新,随着使用友盟服务的时间增加,渐渐放弃了这种想法,转而研究如何更充分的使用,这里分享一下使用自动更新组件的心 ...
- 分析nuget源码,用nuget + nuget.server实现winform程序的自动更新
源起 (个人理解)包管理最开始应该是从java平台下的maven开始吧,因为java的开发大多数是基于开源组件开发的,一个开源包在使用时很可能要去依赖其他的开源包,而且必须是特定的版本才可以.以往在找 ...
- Winform 打包 混淆 自动更新
路径: 最终的解决方案是,ConfuserEx+Installshield+AutoUpdater.NET,ConfuserEx做代码混淆工作,Installshield可以解决注册表的问题,Auto ...
- winform、C# 自动更新
用IIS或者是Tomcat搭建一个Web服务器,因为没有涉及到动态页面,所以用什么服务器无所谓,网上有太多资料,这里不再赘述. 废话不多说,直接上代码. HttpHelper, 访问网页,下载文件等 ...
- c/s应用程序自动更新组件GeneralUpdate3.2.1发布
一.组件简介 GeneralUpdate是基于.net standard 开发的一款(c/s应用)自动升级程序.该组件将更新的核心部分抽离出来方便应用于多种项目当中目前适用于wpf,控制台应用,win ...
- winform应用程序自动更新版本
http://blog.csdn.net/gxxloveszj/article/details/8278187 http://www.cnblogs.com/x369/articles/105656. ...
随机推荐
- 《理解 ES6》阅读整理:函数(Functions)(七)Block-Level Functions
块级函数(Block-Level Functions) 在ES3及以前,在块内声明一个函数会报语法错误,但是所有的浏览器都支持块级函数.不幸的是,每个浏览器在支持块级函数方面都有一些细微的不同的行为. ...
- linux下显示dd命令的进度:
linux下显示dd命令的进度: dd if=/dev/zero of=/tmp/zero.img bs=10M count=100000 想要查看上面的dd命令的执行进度,可以使用下面几种方法: 比 ...
- Python小爬虫练习
# coding: utf-8 __author__ = 'zhangcx' from urllib3 import PoolManager import codecs import json cla ...
- 批量修改vss工作目录
vss作为源代码版本控制工具,可以针对不同的文件夹设置不同的本地工作目录,这样可以方便我们不同的个性化需求.但是往往实际情况是,我们设置了不同的工作目录,后来却发现导致引用混乱,每个人每次获取项目文件 ...
- 冲刺阶段 day11
项目进展:系部,专业,班级管理这三项没有学生,教师管理部分输入项目多,所以窗体搭建比较简单,代码也简单一些,进行的还算顺利,有了之前的编写经验,很多代码可以直接copy过来,越进行编写越顺利了,已经进 ...
- .NET开发笔记(二十二) .NET VS Java
我们目前对.NET的理解大部分可以归纳为:起初它是Java平台(注意是平台,不要跟Java语言搞混淆)的一个克隆品,后来慢慢演变,有了自己的特性.由于Java平台最显著的特点就是“平台独立性”(或者说 ...
- Silverlight无法启动调试,错误“Unable to start debugging. The Silverlight Developer Runtime is not installed. Please install a matching version.” 解决办法
今天调试Silverlight出现了以下错误: 意思是“无法启动调试,因为Silverlight Developer Runtime没有安装,请安装一个匹配的版本”.但是按Ctrl + F5可以调试运 ...
- json-smart 使用示例(推荐fastjson)
关于json库,请使用fastjson,这是我用过的最好用的json库! 地址:https://github.com/alibaba/fastjson ======================== ...
- java.sql.SQLException: No suitable driver 问题解决
最近在学习java,用到c3p0数据库连接池,遇到一个很奇怪的现象,用main方法测试是可以正常连接数据库的,但是使用jsp调用代码,就会报如下图的错误! 最下面的java.sql.SQLExcept ...
- zend studio 常用快捷键
zend studio是一款很棒的PHP语言编译器,强大的功能让很多程序员爱不释手,而快捷键更是程序员加快编写代码的利器,那么一起来看看有哪些好用的快捷键吧. 复制当前行:ctrl+alt+↓ 删除当 ...