using AutoUpdater.Entity;
|
using AutoUpdater.Util;
|
using ICSharpCode.SharpZipLib.Zip;
|
using log4net;
|
using Microsoft.Win32;
|
using System;
|
using System.Collections.Generic;
|
using System.Diagnostics;
|
using System.IO;
|
using System.Reflection;
|
using System.Threading;
|
using System.Windows;
|
using VersionControl;
|
using Path = System.IO.Path;
|
|
namespace AutoUpdater
|
{
|
/// <summary>
|
/// MainWindow.xaml 的交互逻辑
|
/// </summary>
|
public partial class MainWindow : Window
|
{
|
private static ILog Logger = LogManager.GetLogger("AutoUpdater");
|
#region 字段
|
/// <summary>
|
/// SolidWorks 主窗口进程PID
|
/// </summary>
|
private int SwMainProcessId { get; set; } = -1;
|
|
/// <summary>
|
/// exe文件路径
|
/// </summary>
|
private DirectoryInfo CurrentPath { get; set; }
|
|
/// <summary>
|
/// 更新时所用的临时文件夹
|
/// </summary>
|
private string TempDir { get; set; }
|
|
/// <summary>
|
/// 下载文件的临时路径
|
/// </summary>
|
private string DownloadDir { get; set; }
|
|
/// <summary>
|
/// 临时解压缩文件夹
|
/// </summary>
|
private string UnZipDir { get; set; }
|
|
/// <summary>
|
/// SolidWorks程序启动路径
|
/// </summary>
|
private string SwAppPath { get; set; }
|
|
/// <summary>
|
/// 要更新的AppId
|
/// </summary>
|
private string AppId { get; set; }
|
/// <summary>
|
/// 本地版本
|
/// </summary>
|
private string CurrentVersion { get; set; }
|
#endregion
|
|
public MainWindow()
|
{
|
InitializeComponent();
|
}
|
|
/// <summary>
|
/// 窗口加载完成后执行,关掉SolidWorks主进程,进行更新操作
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
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();
|
}
|
}
|
}
|
}
|
|
/// <summary>
|
/// 终止两个Listener相关进程
|
/// </summary>
|
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);
|
}
|
|
/// <summary>
|
/// 启动Listener相关进程
|
/// </summary>
|
public void StartListenerProcess()
|
{
|
try
|
{
|
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();
|
}
|
}
|
catch (Exception ex)
|
{
|
Logger.Error("Start Listener Process Error!", ex);
|
}
|
}
|
|
public void Init()
|
{
|
label.Content = "准备更新程序...";
|
bar.IsIndeterminate = true;
|
}
|
|
/// <summary>
|
/// 初始化下载文件夹
|
/// </summary>
|
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);
|
}
|
}
|
|
/// <summary>
|
/// 先检查更新
|
/// </summary>
|
public void CheckPluginUpdate()
|
{
|
label.Content = "检查更新...";
|
bar.IsIndeterminate = true;
|
try
|
{
|
Dictionary<string, object> datas = new Dictionary<string, object>
|
{
|
{
|
"params", new List<Dictionary<string, string>>
|
{
|
new Dictionary<string, string>
|
{
|
{"appId", AppId},
|
{"currentVersion", CurrentVersion},
|
}
|
}
|
}
|
};
|
Result<List<PluginInfo>> result =
|
HttpUtil.GetClient().PostSyncAction<List<PluginInfo>>(datas, "plugin/openApi/checkUpdate");
|
List<PluginInfo> 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;
|
}
|
}
|
|
/// <summary>
|
/// 如果有需要更新的插件,就下载
|
/// </summary>
|
/// <param name="updates">需要更新的插件信息</param>
|
private async void DownloadReleasePlugin(List<PluginInfo> 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;
|
}
|
}
|
|
/// <summary>
|
/// 下载压缩包后,解压缩并替换插件文件
|
/// </summary>
|
/// <param name="localFilePath">下载的zip路径</param>
|
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();
|
}
|
|
/// <summary>
|
/// 检查自启动注册表
|
/// </summary>
|
private void CheckAutoRunRegKey()
|
{
|
RegistryKey root = null;
|
RegistryKey key = null;
|
try
|
{
|
root = Registry.CurrentUser;
|
key = root.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
|
string name = "SolidWorksListener";
|
if (key == null)
|
{
|
key = root.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
|
}
|
// 没有路径或者路径指向exe不对,就更新自启动路径
|
string listenerPath = key.GetValue(name)?.ToString();
|
string rootDir = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent.Parent.FullName;
|
string newPath = Path.Combine(rootDir, "Listener", "SolidWorksListener.exe");
|
//listenerPath = listenerPath.Replace("\"", "");
|
if (string.IsNullOrEmpty(listenerPath) || new Uri(listenerPath) != new Uri(newPath))
|
{
|
key.SetValue(name, newPath, RegistryValueKind.String);
|
}
|
}
|
catch (Exception e)
|
{
|
Logger.Error("CheckAutoRunRegKey Failed!", e);
|
}
|
finally
|
{
|
try
|
{
|
if (key != null) key.Close();
|
if (root != null) root.Close();
|
}
|
catch (Exception ex)
|
{
|
Logger.Error("Reg Key Close Failed!", ex);
|
}
|
}
|
}
|
|
private void BeforeRestart()
|
{
|
CheckAutoRunRegKey();
|
// 启动监听进程
|
StartListenerProcess();
|
}
|
|
private void DoFinished()
|
{
|
BeforeRestart();
|
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();
|
}
|
}
|
}
|