using AutoUpdater.Entity; using AutoUpdater.Util; using ICSharpCode.SharpZipLib.Zip; using log4net; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using System.Windows; using VersionControl; using Path = System.IO.Path; namespace AutoUpdater { /// /// MainWindow.xaml 的交互逻辑 /// public partial class MainWindow : Window { private static ILog Logger = LogManager.GetLogger("AutoUpdater"); #region 字段 /// /// SolidWorks 主窗口进程PID /// private int SwMainProcessId { get; set; } = -1; /// /// exe文件路径 /// private DirectoryInfo CurrentPath { get; set; } /// /// 更新时所用的临时文件夹 /// private string TempDir { get; set; } /// /// 下载文件的临时路径 /// private string DownloadDir { get; set; } /// /// 临时解压缩文件夹 /// private string UnZipDir { get; set; } /// /// SolidWorks程序启动路径 /// private string SwAppPath { get; set; } /// /// 要更新的AppId /// private string AppId { get; set; } /// /// 本地版本 /// private string CurrentVersion { get; set; } #endregion public MainWindow() { InitializeComponent(); } /// /// 窗口加载完成后执行,关掉SolidWorks主进程,进行更新操作 /// /// /// private void Window_Loaded(object sender, RoutedEventArgs e) { Logger.Info("自动更新程序启动..."); string[] args = Environment.GetCommandLineArgs(); // 有参数,说明是从SolidWork插件启动的,需要kill solidwork进程 SwMainProcessId = args.Length >= 2 ? int.Parse(args[1]) : -1; // 初始化程序路径 CurrentPath = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent; Init(); if (SwMainProcessId > 0) { // 可能需要关进程,可能不需要 Close_SwMainProcess(); } else { // 从exe文件中获取本地插件版本 GetCurrentVersion(); // 检查插件的更新 CheckPluginUpdate(); } } public void KillProcessByFullPath(string exePath) { string exeName = Path.GetFileNameWithoutExtension(exePath); Process[] ps = Process.GetProcessesByName(exeName); if (ps.Length > 0) { foreach (Process p in ps) { if (new Uri(p.MainModule.FileName) == new Uri(exePath)) { p.Kill(); } } } } /// /// 终止两个Listener相关进程 /// public void KillListenerProcess() { string dir = Path.GetDirectoryName(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); string path1 = Path.Combine(dir, "Listener", "SolidWorksListener.exe"); string path2 = Path.Combine(dir, "Alert.exe"); KillProcessByFullPath(path1); // 暂停一秒不然AlertKill不掉 Thread.Sleep(1000); KillProcessByFullPath(path2); } /// /// 启动Listener相关进程 /// public void StartListenerProcess() { string dir = Path.GetDirectoryName(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); string path1 = Path.Combine(dir, "Listener", "SolidWorksListener.exe"); if (File.Exists(path1)) { ProcessStartInfo info = new ProcessStartInfo { FileName = path1, WorkingDirectory = Path.GetDirectoryName(path1) }; new Process { StartInfo = info }.Start(); } } public void Init() { label.Content = "准备更新程序..."; bar.IsIndeterminate = true; } /// /// 初始化下载文件夹 /// public void InitDownloadDir() { try { string tempDir = "temp"; string downloadDir = "download"; // 创建临时文件夹 TempDir = $"{CurrentPath.FullName}{Path.DirectorySeparatorChar}{tempDir}"; if (!Directory.Exists(TempDir)) { Directory.CreateDirectory(TempDir); } // 创建临时文件夹下的下载文件夹 DownloadDir = $"{TempDir}{Path.DirectorySeparatorChar}{downloadDir}"; if (!Directory.Exists(DownloadDir)) { Directory.CreateDirectory(DownloadDir); } } catch (Exception e) { Logger.Error("创建下载文件夹失败!异常:{0}", e); MessageBox.Show("创建下载文件夹失败!请重试", "错误", MessageBoxButton.OK, MessageBoxImage.Error); Environment.Exit(1); } } public void InitUnZipDir() { try { string tempDir = "temp"; string unzipDir = "unzip"; // 创建临时文件夹 TempDir = $"{CurrentPath.FullName}{Path.DirectorySeparatorChar}{tempDir}"; if (!Directory.Exists(TempDir)) { Directory.CreateDirectory(TempDir); } // 创建临时文件夹下的下载文件夹 UnZipDir = $"{TempDir}{Path.DirectorySeparatorChar}{unzipDir}"; if (!Directory.Exists(UnZipDir)) { Directory.CreateDirectory(UnZipDir); } } catch (Exception e) { Logger.Error("创建临时解压文件夹失败!异常:{0}", e); MessageBox.Show("创建临时解压文件夹失败!请重试", "错误", MessageBoxButton.OK, MessageBoxImage.Error); Environment.Exit(1); } } /// /// 先检查更新 /// public void CheckPluginUpdate() { label.Content = "检查更新..."; bar.IsIndeterminate = true; try { Dictionary datas = new Dictionary { { "params", new List> { new Dictionary { {"appId", AppId}, {"currentVersion", CurrentVersion}, } } } }; Result> result = HttpUtil.GetClient().PostSyncAction>(datas, "plugin/openApi/checkUpdate"); List updates = result.HandleResult(); if (updates == null || updates.Count <= 0) { label.Content = "当前为最新版本!"; bar.IsIndeterminate = false; return; } DownloadReleasePlugin(updates); } catch (Exception e) { Logger.Error("检查更新错误!异常:{0}", e); MessageBox.Show("检查更新错误!请重试", "错误", MessageBoxButton.OK, MessageBoxImage.Error); label.Content = "检查更新错误!请重试"; bar.IsIndeterminate = false; } } /// /// 如果有需要更新的插件,就下载 /// /// 需要更新的插件信息 private async void DownloadReleasePlugin(List updates) { InitDownloadDir(); label.Content = "下载更新文件中,请勿关闭程序..."; PluginInfo update = updates[0]; try { string localFilePath = await HttpUtil.GetClient().GetDownload($"plugin/openApi/downloadReleasePlugin/{update.id}", DownloadDir, "Latest"); UnZipAndUpdateFile(localFilePath); } catch (Exception e) { Logger.Error("下载更新文件错误!异常:{0}", e); MessageBox.Show("下载更新文件错误!请重试", "错误", MessageBoxButton.OK, MessageBoxImage.Error); label.Content = "下载更新文件错误!请重试"; bar.IsIndeterminate = false; } } /// /// 下载压缩包后,解压缩并替换插件文件 /// /// 下载的zip路径 private async void UnZipAndUpdateFile(string localFilePath) { if (Path.GetExtension(localFilePath).ToLower() != ".zip") { return; } label.Content = "下载完成,解压中,请勿关闭程序..."; // 临时解压目录,防止解压出错 InitUnZipDir(); // kill掉监听程序,避免文件占用 KillListenerProcess(); // 等待一秒释放exe占用 Thread.Sleep(1000); // 插件文件夹 默认在 AutoUpdater.exe 的上级目录中 string pluginDir = new DirectoryInfo(TempDir).Parent.Parent.FullName; using (ZipInputStream zipIn = new ZipInputStream(File.Open(localFilePath, FileMode.Open))) { ZipEntry zipEntry; while ((zipEntry = zipIn.GetNextEntry()) != null) { string zipFileName = zipEntry.Name, targetFileName; zipFileName = zipFileName.Replace("AutoUpdater/", "WaitingUpdate/"); targetFileName = Path.Combine(pluginDir, zipFileName); if (zipEntry.IsDirectory) { if (!Directory.Exists(targetFileName)) { Directory.CreateDirectory(targetFileName); } } else { using (FileStream fs = new FileStream(targetFileName, FileMode.Create)) { byte[] buffer = new byte[1024]; int readLength = 0; int length; while ((length = await zipIn.ReadAsync(buffer, 0, buffer.Length)) != 0) { readLength += length; fs.Write(buffer, 0, length); } } } } } DoFinished(); } private void DoFinished() { // 启动监听进程 StartListenerProcess(); label.Content = "更新完成"; bar.IsIndeterminate = false; if (SwAppPath != null) { MessageBoxResult mr = MessageBox.Show("更新完成,是否启动SolidWorks?", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Question); if (mr == MessageBoxResult.OK) { Process swProcess = new Process { StartInfo = new ProcessStartInfo { FileName = SwAppPath } }; swProcess.Start(); } } Environment.Exit(0); } private void GetCurrentVersion() { Thread.Sleep(1000); try { var data = VersionUtil.GetRegPluginVersion(); this.AppId = data[VersionUtil.APPID_KEY]; this.CurrentVersion = data[VersionUtil.VERSION_KEY]; } catch (NoSoftwareKeyException e) { Logger.Error("Get plugin version failed,SwPlugin software reg not found.", e); MessageBox.Show("获取插件当前版本失败!请打开插件重试"); Environment.Exit(1); } catch (Exception e) { Logger.Error("Get plugin version failed.", e); MessageBox.Show("获取插件当前版本失败!请重试"); Environment.Exit(1); } } private void Close_SwMainProcess() { try { Process swMainProcess = Process.GetProcessById(SwMainProcessId); if (swMainProcess != null) { // 获取 SW 路径 SwAppPath = swMainProcess.MainModule.FileName; swMainProcess.EnableRaisingEvents = true; swMainProcess.Exited += new EventHandler(SwMainProcessExited); if (!swMainProcess.CloseMainWindow()) { MessageBoxResult mr = MessageBox.Show("不能关闭SolidWorks主窗口!请手动退出SolidWorks后点击确认按钮,或点击取消退出更新程序", "错误", MessageBoxButton.OKCancel, MessageBoxImage.Error); if (mr == MessageBoxResult.OK) { Thread.Sleep(1000); Close_SwMainProcess(); } Environment.Exit(1); } } } catch (Exception ex) { //Dispatcher.Invoke(new Action(delegate //{ // SwMainProcessId = -1; // // 从exe文件中获取本地插件版本 // GetCurrentVersion(); // // 检查插件的更新 // CheckPluginUpdate(); //})); Logger.Error("不能关闭 SolidWorks主窗口!异常:{0}", ex); MessageBoxResult mr = MessageBox.Show("不能关闭SolidWorks主窗口!请手动退出SolidWorks后点击确认按钮,或点击取消退出更新程序", "错误", MessageBoxButton.OKCancel, MessageBoxImage.Error); if (mr == MessageBoxResult.OK) { Thread.Sleep(1000); Close_SwMainProcess(); } Environment.Exit(1); } } void SwMainProcessExited(object sender, object e) { Dispatcher.Invoke(new Action(delegate { SwMainProcessId = -1; // 从exe文件中获取本地插件版本 GetCurrentVersion(); // 检查插件的更新 CheckPluginUpdate(); })); } private void Button_Click(object sender, RoutedEventArgs e) { CheckPluginUpdate(); } } }