一个自动更新的简单实现(通过反射解耦)
更新模块的代码:
代码
更新模块的UI:
代码
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
}
XmlDocument doc = new XmlDocument();
#region "Disable the 'X'"
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
const int CS_NOCLOSE = 0x200;
cp.ClassStyle = cp.ClassStyle | CS_NOCLOSE;
return cp;
}
}
#endregion
private void FrmMain_Load(object sender, EventArgs e)
{
string config = Path.Combine(Path.GetTempPath(),"Updater.xml");
doc.Load(config);
this.lblProduct.Text = doc.SelectSingleNode("/Updater/ProductName").InnerText;
this.lblNewVer.Text = "new version:" + doc.SelectSingleNode("/Updater/Version").InnerText;
this.lblOriginVer.Text = "old version:" + UpdaterModule.Version;
MethodInvoker mi = new MethodInvoker(UpdateSys);
mi.BeginInvoke(new AsyncCallback(Finished),null);
}
private void Finished(IAsyncResult result)
{
if (result.IsCompleted)
{
Process.Start(Path.Combine(Application.StartupPath,doc.SelectSingleNode("/Updater/MainExe").InnerText));
this.Close();
}
}
private delegate void StringDelegate(string info);
private delegate void IntDelegate(int value);
private void SetInfo(string info)
{
if (this.InvokeRequired)
{
this.Invoke(new StringDelegate(SetInfo), info);
return;
}
else
{
this.lblInfo.Text = info;
}
}
private void SetTotalValue()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(SetTotalValue));
return;
}
else
{
this.pbTotal.Value++;
}
}
private void SetTotalMax(int value)
{
if (this.InvokeRequired)
{
this.Invoke(new IntDelegate(SetTotalMax), value);
return;
}
else
{
this.pbTotal.Maximum = value;
}
}
private void UpdateSys()
{
if (UpdaterModule.Debug)
{
System.Diagnostics.Debugger.Break();
}
//根据临时文件夹中的文件进行下载
WebClient wc = new WebClient();
string updatePath = doc.SelectSingleNode("/Updater/UpdatePath").InnerText;
XmlNodeList xnl = doc.SelectNodes("/Updater/Files/File");
SetTotalMax(xnl.Count);
foreach (XmlNode xn in xnl)
{
try
{
string localFile = Path.Combine(Application.StartupPath, xn.Attributes["Name"].Value);
string dir = Path.GetDirectoryName(localFile);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
SetInfo("processing:" + localFile);
wc.DownloadFile(GetUri(updatePath, xn.Attributes["Name"].Value), localFile);
}
catch (Exception)
{
if (UpdaterModule.Debug)
{
Debugger.Break();
}
}
SetTotalValue();
}
}
static string GetUri(string uri, string filename)
{
return (uri.Trim('/') + "/" + filename.Trim('/')).Replace('\\','/');
}
string GetTempDir()
{
string dir = Path.GetTempPath();
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
return dir;
}
}
{
public FrmMain()
{
InitializeComponent();
}
XmlDocument doc = new XmlDocument();
#region "Disable the 'X'"
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
const int CS_NOCLOSE = 0x200;
cp.ClassStyle = cp.ClassStyle | CS_NOCLOSE;
return cp;
}
}
#endregion
private void FrmMain_Load(object sender, EventArgs e)
{
string config = Path.Combine(Path.GetTempPath(),"Updater.xml");
doc.Load(config);
this.lblProduct.Text = doc.SelectSingleNode("/Updater/ProductName").InnerText;
this.lblNewVer.Text = "new version:" + doc.SelectSingleNode("/Updater/Version").InnerText;
this.lblOriginVer.Text = "old version:" + UpdaterModule.Version;
MethodInvoker mi = new MethodInvoker(UpdateSys);
mi.BeginInvoke(new AsyncCallback(Finished),null);
}
private void Finished(IAsyncResult result)
{
if (result.IsCompleted)
{
Process.Start(Path.Combine(Application.StartupPath,doc.SelectSingleNode("/Updater/MainExe").InnerText));
this.Close();
}
}
private delegate void StringDelegate(string info);
private delegate void IntDelegate(int value);
private void SetInfo(string info)
{
if (this.InvokeRequired)
{
this.Invoke(new StringDelegate(SetInfo), info);
return;
}
else
{
this.lblInfo.Text = info;
}
}
private void SetTotalValue()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(SetTotalValue));
return;
}
else
{
this.pbTotal.Value++;
}
}
private void SetTotalMax(int value)
{
if (this.InvokeRequired)
{
this.Invoke(new IntDelegate(SetTotalMax), value);
return;
}
else
{
this.pbTotal.Maximum = value;
}
}
private void UpdateSys()
{
if (UpdaterModule.Debug)
{
System.Diagnostics.Debugger.Break();
}
//根据临时文件夹中的文件进行下载
WebClient wc = new WebClient();
string updatePath = doc.SelectSingleNode("/Updater/UpdatePath").InnerText;
XmlNodeList xnl = doc.SelectNodes("/Updater/Files/File");
SetTotalMax(xnl.Count);
foreach (XmlNode xn in xnl)
{
try
{
string localFile = Path.Combine(Application.StartupPath, xn.Attributes["Name"].Value);
string dir = Path.GetDirectoryName(localFile);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
SetInfo("processing:" + localFile);
wc.DownloadFile(GetUri(updatePath, xn.Attributes["Name"].Value), localFile);
}
catch (Exception)
{
if (UpdaterModule.Debug)
{
Debugger.Break();
}
}
SetTotalValue();
}
}
static string GetUri(string uri, string filename)
{
return (uri.Trim('/') + "/" + filename.Trim('/')).Replace('\\','/');
}
string GetTempDir()
{
string dir = Path.GetTempPath();
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
return dir;
}
}
配置文件:
代码
调用方:
代码
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
bool flag = false;
Assembly assm = typeof(Program).Assembly;
Mutex mutex = new Mutex(true, ((GuidAttribute)(assm.GetCustomAttributes(typeof(GuidAttribute), false)[0])).Value, out flag);
if (!flag)
{
MessageBox.Show("已经存在一个数据化病案系统,无法再启动!");
}
else
{
//自动更新
SyscUpdateModule();
if (IsServerActive())
{
if (IsVersionAvailable() == DialogResult.Yes)
{
Update();
}
else
{
StartApp();
}
}
else
{
StartApp();
}
}
}
static void StartApp()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
FrmLogin frmLogin = new FrmLogin();
if (frmLogin.ShowDialog() == DialogResult.OK)
{
WinFormsHelper.FindContentOrCreate<FrmMRViewer>().Hide();
Application.Run(FrmMain.Instance);
//Application.Run(new FrmSpecialMR());
}
}
static bool IsServerActive()
{
string assemFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Updater.exe");
Assembly assem = Assembly.LoadFrom(assemFile);
Type type = assem.GetType("Updater.UpdaterModule");
Object instant = Activator.CreateInstance(type);
MethodInfo miCheck = type.GetMethod("IsServerActive");
return (bool)miCheck.Invoke(instant, null);
}
static DialogResult IsVersionAvailable()
{
string assemFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Updater.exe");
Assembly assem = Assembly.LoadFrom(assemFile);
Type type = assem.GetType("Updater.UpdaterModule");
Object instant = Activator.CreateInstance(type);
MethodInfo miUpdate = type.GetMethod("IsVersionAvailable");
return (DialogResult)miUpdate.Invoke(instant, null);
}
static void Update()
{
Process.Start(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Updater.exe"));
Application.Exit();
}
/// <summary>
/// 更新更新文件
/// </summary>
static void SyscUpdateModule()
{
try
{
string localFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Updater.exe");
FileInfo localFI = new FileInfo(localFile);
XPathDocument doc = new XPathDocument(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Updater.xml"));
XPathNavigator nav = doc.CreateNavigator();
string updatePath = nav.SelectSingleNode("/Updater/UpdatePath").Value;
string remoteFile = GetUri(updatePath, "Updater.exe");
FileInfo remoteFI = DownloadHttpFile(remoteFile);
if (remoteFI.LastWriteTime > localFI.LastWriteTime || localFI.Length != remoteFI.Length)
{
File.Copy(remoteFI.FullName, localFile, true);
}
}
catch (Exception)
{
}
}
static FileInfo DownloadHttpFile(string url)
{
Uri uri = new Uri(url);
string localFile = Path.Combine(GetTempDir(), Path.GetFileName(uri.AbsolutePath));
WebClient wc = new WebClient();
wc.DownloadFile(url, localFile);
return new FileInfo(localFile);
}
static string GetUri(string uri, string filename)
{
return uri.Trim('/') + "/" + filename.Trim('/');
}
static string GetTempDir()
{
string dir = Path.GetTempPath();
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
return dir;
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Form currentForm = null;
if (null != Application.OpenForms && 0 != Application.OpenForms.Count)
{
currentForm = Application.OpenForms[0];
}
Exception ae = e.ExceptionObject as Exception;
if (null != ae)
{
if (null == currentForm)
{
MessageBox.Show(ae.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}
else
{
MessageBox.Show(currentForm, ae.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}
}
}
}
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
bool flag = false;
Assembly assm = typeof(Program).Assembly;
Mutex mutex = new Mutex(true, ((GuidAttribute)(assm.GetCustomAttributes(typeof(GuidAttribute), false)[0])).Value, out flag);
if (!flag)
{
MessageBox.Show("已经存在一个数据化病案系统,无法再启动!");
}
else
{
//自动更新
SyscUpdateModule();
if (IsServerActive())
{
if (IsVersionAvailable() == DialogResult.Yes)
{
Update();
}
else
{
StartApp();
}
}
else
{
StartApp();
}
}
}
static void StartApp()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
FrmLogin frmLogin = new FrmLogin();
if (frmLogin.ShowDialog() == DialogResult.OK)
{
WinFormsHelper.FindContentOrCreate<FrmMRViewer>().Hide();
Application.Run(FrmMain.Instance);
//Application.Run(new FrmSpecialMR());
}
}
static bool IsServerActive()
{
string assemFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Updater.exe");
Assembly assem = Assembly.LoadFrom(assemFile);
Type type = assem.GetType("Updater.UpdaterModule");
Object instant = Activator.CreateInstance(type);
MethodInfo miCheck = type.GetMethod("IsServerActive");
return (bool)miCheck.Invoke(instant, null);
}
static DialogResult IsVersionAvailable()
{
string assemFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Updater.exe");
Assembly assem = Assembly.LoadFrom(assemFile);
Type type = assem.GetType("Updater.UpdaterModule");
Object instant = Activator.CreateInstance(type);
MethodInfo miUpdate = type.GetMethod("IsVersionAvailable");
return (DialogResult)miUpdate.Invoke(instant, null);
}
static void Update()
{
Process.Start(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Updater.exe"));
Application.Exit();
}
/// <summary>
/// 更新更新文件
/// </summary>
static void SyscUpdateModule()
{
try
{
string localFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Updater.exe");
FileInfo localFI = new FileInfo(localFile);
XPathDocument doc = new XPathDocument(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Updater.xml"));
XPathNavigator nav = doc.CreateNavigator();
string updatePath = nav.SelectSingleNode("/Updater/UpdatePath").Value;
string remoteFile = GetUri(updatePath, "Updater.exe");
FileInfo remoteFI = DownloadHttpFile(remoteFile);
if (remoteFI.LastWriteTime > localFI.LastWriteTime || localFI.Length != remoteFI.Length)
{
File.Copy(remoteFI.FullName, localFile, true);
}
}
catch (Exception)
{
}
}
static FileInfo DownloadHttpFile(string url)
{
Uri uri = new Uri(url);
string localFile = Path.Combine(GetTempDir(), Path.GetFileName(uri.AbsolutePath));
WebClient wc = new WebClient();
wc.DownloadFile(url, localFile);
return new FileInfo(localFile);
}
static string GetUri(string uri, string filename)
{
return uri.Trim('/') + "/" + filename.Trim('/');
}
static string GetTempDir()
{
string dir = Path.GetTempPath();
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
return dir;
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Form currentForm = null;
if (null != Application.OpenForms && 0 != Application.OpenForms.Count)
{
currentForm = Application.OpenForms[0];
}
Exception ae = e.ExceptionObject as Exception;
if (null != ae)
{
if (null == currentForm)
{
MessageBox.Show(ae.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}
else
{
MessageBox.Show(currentForm, ae.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}
}
}
}