第二步理論上我們?cè)搶懣蛻舳肆耍牵诖酥埃枰冉榻B下一些必要的方法以及操作。
寫代碼還是要盡量的保證通用性,以便以后需要的時(shí)候可以拿來(lái)稍微改改甚至直接使用。所以在這里我們將自動(dòng)更新的程序抽象出來(lái),即對(duì)于客戶端來(lái)說(shuō),它只包含三個(gè)文件(Autoupdate.dll、Autoupdate.exe、updateList.xml,如果是.NET Framework的話,其實(shí)是沒(méi)有Autoupdate.dll文件的,就一個(gè)exe就足夠了。這也是我為什么一直不用NET Core來(lái)寫Winform程序的原因之一);然后將這三個(gè)文件放到主程序的目錄中即可。
然后就是傳參調(diào)用,在Program文件中做了以下代碼操作。所以調(diào)用的時(shí)候需要將主程序的執(zhí)行目錄以及進(jìn)程名傳過(guò)來(lái),作用分別是再更新完后自動(dòng)啟動(dòng)以及更新之前把相關(guān)的進(jìn)程殺掉以便完成更新。
同時(shí)可以看到在更新的時(shí)候,有一個(gè)圖片旋轉(zhuǎn)的動(dòng)作,也一并放到此篇文章中。
開發(fā)環(huán)境:.NET Core 3.1
開發(fā)工具: Visual Studio 2019
實(shí)現(xiàn)代碼:
namespace Autoupdate {
static class Program {
[STAThread]
static void Main(string[] args) {
if(args.Length != 1) {
return;
}
var arg = args[0].Split("|*|");
if(arg.Length == 0) {
return;
}
string runPath = arg[0];
string procesName = arg[1];
Process[] processes = Process.GetProcesses();
foreach(Process process in processes) {
if(process.ProcessName == procesName) {
process.Kill(true);
}
}
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form_update(runPath));
}
}
}
namespace Autoupdate.Test {
static class Program {
[STAThread]
static void Main() {
update();
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
readonly static string updateXml = Application.StartupPath + "updateList.xml";
static string GetupdateUrl() {
XElement xele = XElement.Load(updateXml);
string url = xele.Element("url").Value;
return url;
}
static string GetupdateFiles() {
XDocument xdoc = XDocument.Load(updateXml);
var files = from f in xdoc.Root.Element("files").Elements() select new { name = f.Attribute("name").Value, version = f.Attribute("version").Value };
return JsonConvert.SerializeObject(files);
}
static bool Checkupdate() {
string url = GetupdateUrl();
HttpResult httpResult = HttpUtil.HttpRequest(new HttpItem(url + "GetupdateFiles", requestData: GetupdateFiles()));
if(httpResult.Status) {
updateModel_Out output = JsonConvert.DeserializeObject<updateModel_Out>(httpResult.HttpStringData);
if(output.updateList.Count > 0)
return true;
}
return false;
}
static void update() {
if(Checkupdate()) {
string processName = Assembly.GetexecutingAssembly().GetName().Name;
ProcessStartInfo info = new ProcessStartInfo(Application.StartupPath + "Autoupdate.exe", Process.GetCurrentProcess().MainModule.FileName + "|*|" + processName);
Process.Start(info);
Environment.Exit(0);
}
}
}
}
public static class ImageEx {
public static Image RotateImage(this Image image, float angle) {
if(image == null)
throw new ArgumentNullException("image");
float dx = image.Width / 2.0f;
float dy = image.Height / 2.0f;
Bitmap rotatedBmp = new Bitmap(image.Width, image.Height);
rotatedBmp.SetResolution(image.HorizontalResolution, image.VerticalResolution);
Graphics g = Graphics.fromImage(rotatedBmp);
g.TranslateTransform(dx, dy);
g.RotateTransform(angle);
g.TranslateTransform(-dx, -dy);
g.DrawImage(image, new PointF(0, 0));
g.Dispose();
return rotatedBmp;
}
}
實(shí)現(xiàn)效果:
代碼解析:這里可以關(guān)注下在主程序中的獲取更新地址以及文件等方法,其實(shí)我這里是有重復(fù)判斷的,即在主程序中判斷了一遍,還會(huì)在更新程序中判斷一遍,如果覺(jué)得不需要,可以執(zhí)行選擇去掉,全部交給更新程序去做。但是也就需要統(tǒng)一放在更新程序的入口中做處理了,相對(duì)而言,我覺(jué)得寫兩遍還是很方便。
該文章在 2023/2/27 10:15:34 編輯過(guò)