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
{
///
/// 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()
{
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;
}
///
/// 初始化下载文件夹
///
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 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();
}
}
}