第二步理論上我們該寫客戶端了,但是,在此之前,需要先介紹下一些必要的方法以及操作。
寫代碼還是要盡量的保證通用性,以便以后需要的時候可以拿來稍微改改甚至直接使用。所以在這里我們將自動更新的程序抽象出來,即對于客戶端來說,它只包含三個文件(Autoupdate.dll、Autoupdate.exe、updateList.xml,如果是.NET Framework的話,其實是沒有Autoupdate.dll文件的,就一個exe就足夠了。這也是我為什么一直不用NET Core來寫Winform程序的原因之一);然后將這三個文件放到主程序的目錄中即可。
然后就是傳參調(diào)用,在Program文件中做了以下代碼操作。所以調(diào)用的時候需要將主程序的執(zhí)行目錄以及進程名傳過來,作用分別是再更新完后自動啟動以及更新之前把相關的進程殺掉以便完成更新。
同時可以看到在更新的時候,有一個圖片旋轉的動作,也一并放到此篇文章中。
開發(fā)環(huán)境:.NET Core 3.1
開發(fā)工具: Visual Studio 2019
實現(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;
}
}
實現(xiàn)效果:
代碼解析:這里可以關注下在主程序中的獲取更新地址以及文件等方法,其實我這里是有重復判斷的,即在主程序中判斷了一遍,還會在更新程序中判斷一遍,如果覺得不需要,可以執(zhí)行選擇去掉,全部交給更新程序去做。但是也就需要統(tǒng)一放在更新程序的入口中做處理了,相對而言,我覺得寫兩遍還是很方便。
該文章在 2023/2/27 10:15:34 編輯過