RaUI/Source/rycUpdate/Frmmain.cs

503 lines
20 KiB
C#
Raw Normal View History

using ryCommon;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO.Compression;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace rycUpdate
{
public partial class Frmmain : Form
{
string ParamStr = "";
public Frmmain(string[] args)
{
InitializeComponent();
if (args.Length >= 1)
{
ParamStr = args[0];
}
}
/// <summary>
///
/// </summary>
public enum ShowCommands : int
{
/// <summary>
///
/// </summary>
SW_HIDE = 0,
/// <summary>
///
/// </summary>
SW_SHOWNORMAL = 1,
/// <summary>
///
/// </summary>
SW_NORMAL = 1,
/// <summary>
///
/// </summary>
SW_SHOWMINIMIZED = 2,
/// <summary>
///
/// </summary>
SW_SHOWMAXIMIZED = 3,
/// <summary>
///
/// </summary>
SW_MAXIMIZE = 3,
/// <summary>
///
/// </summary>
SW_SHOWNOACTIVATE = 4,
/// <summary>
///
/// </summary>
SW_SHOW = 5,
/// <summary>
///
/// </summary>
SW_MINIMIZE = 6,
/// <summary>
///
/// </summary>
SW_SHOWMINNOACTIVE = 7,
/// <summary>
///
/// </summary>
SW_SHOWNA = 8,
/// <summary>
///
/// </summary>
SW_RESTORE = 9,
/// <summary>
///
/// </summary>
SW_SHOWDEFAULT = 10,
/// <summary>
///
/// </summary>
SW_FORCEMINIMIZE = 11,
/// <summary>
///
/// </summary>
SW_MAX = 11
}
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
static extern int ShellExecute(
IntPtr hwnd,
string lpOperation,
string lpFile,
string lpParameters,
string lpDirectory,
ShowCommands nShowCmd);
/// <summary>
/// /运行文件
/// </summary>
/// <param name="FilePath"></param>
/// <param name="PramCom"></param>
/// <param name="lpDirectory"></param>
/// <param name="RunMode"></param>
/// <returns></returns>
public static int RunFile(string FilePath, string PramCom, string lpDirectory, int RunMode = 0)
{
try
{
var WindowStyle = ShowCommands.SW_SHOWNORMAL;
switch (RunMode)
{
case 0:
WindowStyle = ShowCommands.SW_SHOWNORMAL;
break;
case 1:
WindowStyle = ShowCommands.SW_HIDE;
break;
case 2:
WindowStyle = ShowCommands.SW_SHOWMINIMIZED;
break;
case 3:
WindowStyle = ShowCommands.SW_SHOWMAXIMIZED;
break;
}
return ShellExecute(IntPtr.Zero, "open", FilePath, PramCom, lpDirectory, WindowStyle);
//System.Diagnostics.Process.Start(FilePath, PramCom);
//return 1;
}
catch { return 0; }
}
private void ShowState(string text)
{
LblState.Text = "状态:" + text;
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
[StructLayout(LayoutKind.Sequential)]
public struct PROCESSENTRY32
{
public uint dwSize;
public uint cntUsage;
public uint th32ProcessID;
public IntPtr th32DefaultHeapID;
public uint th32ModuleID;
public uint cntThreads;
public uint th32ParentProcessID;
public int pcPriClassBase;
public uint dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szExeFile;
}
const uint TH32CS_SNAPPROCESS = 0x00000002;
const uint PROCESS_TERMINATE = 0x0001;
[DllImport("psapi.dll")]
static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In][MarshalAs(UnmanagedType.U4)] int nSize);
/// <summary>
/// 获取进程路径
/// </summary>
/// <param name="pid"></param>
/// <returns></returns>
public static string GetPath(uint pid)
{
var processHandle = OpenProcess(0x0400 | 0x0010, false, pid);
if (processHandle == IntPtr.Zero)
{
return null;
}
const int lengthSb = 4000;
var sb = new StringBuilder(lengthSb);
string result = "";
if (GetModuleFileNameEx(processHandle, IntPtr.Zero, sb, lengthSb) > 0)
{
result = sb.ToString();
}
CloseHandle(processHandle);
return result;
}
public static bool EndProcess(string fileName)
{
IntPtr snapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshotHandle == IntPtr.Zero)
return false;
PROCESSENTRY32 processEntry = new PROCESSENTRY32();
processEntry.dwSize = (uint)Marshal.SizeOf(processEntry);
bool continueLoop = Process32First(snapshotHandle, ref processEntry);
bool result = true;
List<uint> list= new List<uint>();
var cur_id = Process.GetCurrentProcess().Id;
while (continueLoop)
{
if (string.Equals(processEntry.szExeFile, fileName, StringComparison.OrdinalIgnoreCase))
{
if (cur_id != processEntry.th32ProcessID)
list.Add(processEntry.th32ProcessID);
}
continueLoop = Process32Next(snapshotHandle, ref processEntry);
}
CloseHandle(snapshotHandle);
for (int i = 0; i < list.Count; i++)
{
if(!TerminateProcess(OpenProcess(PROCESS_TERMINATE, false, list[i]), 0))
{
result = false;
}
}
return result;
}
public static bool EndProcessByFolder(string Folder)
{
IntPtr snapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshotHandle == IntPtr.Zero)
return false;
PROCESSENTRY32 processEntry = new PROCESSENTRY32();
processEntry.dwSize = (uint)Marshal.SizeOf(processEntry);
bool continueLoop = Process32First(snapshotHandle, ref processEntry);
bool result = true;
var _Folder = Folder.ToLower().Trim('\\');
List<uint> list = new List<uint>();
var cur_id = Process.GetCurrentProcess().Id;
while (continueLoop)
{
var process_path = GetPath(processEntry.th32ProcessID);
if (process_path!=null && process_path.Length>0 && System.IO.Path.GetDirectoryName(process_path).Trim('\\').ToLower().IndexOf(_Folder)==0)
{
if(cur_id!= processEntry.th32ProcessID)
list.Add(processEntry.th32ProcessID);
}
continueLoop = Process32Next(snapshotHandle, ref processEntry);
}
CloseHandle(snapshotHandle);
for (int i = 0; i < list.Count; i++)
{
if (!TerminateProcess(OpenProcess(PROCESS_TERMINATE, false, list[i]), 0))
{
result = false;
}
}
return result;
}
private void KillMultiProcess(List<string> list)
{
var process = Process.GetProcesses();
for (int i = 0; i < list.Count; i++)
{
EndProcess(list[i]);
}
}
/// <summary>
/// Base64转字符串
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public string Base64ToStr(string input)
{
try
{
byte[] bpath = Convert.FromBase64String(input);
return System.Text.Encoding.Default.GetString(bpath);
}
catch { return ""; }
}
private bool IsRunning = false;
private void CloseApp()
{
IsRunning = false;
this.Close();
}
public void StartUpdate()
{
IsRunning = true;
var old_filename = "rycUpdate.exe";
var new_filename = "rycUpdate2.exe";
var UpdateZipPath = Application.StartupPath + "\\Update\\tmp.tmp";
var UnZipFolder = Application.StartupPath + "\\Update\\tmp";
BigFileOp bigFileOp = new BigFileOp();
bigFileOp.OnFolderProgress += BigFileOp_OnFolderProgress;
//this.Invoke(new Action(() =>
//{
// progressBar1.Visible = true;
//}));
//var intd = bigFileOp.CopyFolderByProgress("E:\\My Datas\\My Codes\\毕方项目\\CSharp\\ryProcessManager\\Publish\\test", "E:\\My Datas\\My Codes\\毕方项目\\CSharp\\ryProcessManager\\Publish\\test3");
ryCommon.Storage2 MyXml = new ryCommon.Storage2();
MyXml.LoadFromFile(Application.StartupPath + "\\tmp.updx");
MyXml.SelectNode("id", "MainProcName");
var MainProcName = MyXml.GetAttrValue("Value", "");
MyXml.SelectNode("id", "MainProcPram");
var MainProcPram = MyXml.GetAttrValue("Value", "");
if (System.IO.File.Exists(Application.StartupPath+ "\\tmp.updx"))
{
switch(ParamStr)
{
case "update":
if (!System.IO.File.Exists(UpdateZipPath))
{
this.Invoke(new Action(() =>
{
MessageBox.Show("升级文件不存在,升级中断。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
CloseApp();
}));
return;
}
if (System.IO.Directory.Exists(UnZipFolder))
{
bigFileOp.DelFileOrFolder(UnZipFolder);
}
ShowState("正在解包升级文件...");
int error_id = 1000;
string error_msg = "";
try
{
var ZipArchive = ZipFile.OpenRead(UpdateZipPath);
this.Invoke(new Action(() =>
{
progressBar1.Visible = true;
progressBar1.Maximum = ZipArchive.Entries.Count;
}));
for (int i = 0; i < ZipArchive.Entries.Count; i++)
{
var entry = ZipArchive.Entries[i];
if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(UnZipFolder + "\\" + entry.FullName.Replace("/", "\\"))))
{
error_id = 1001;
error_msg = System.IO.Path.GetDirectoryName(UnZipFolder + "\\" + entry.FullName.Replace("/", "\\"));
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(UnZipFolder + "\\" + entry.FullName.Replace("/", "\\")));
}
if (entry.FullName.EndsWith("/"))
{
if (!System.IO.Directory.Exists(UnZipFolder + "\\" + entry.FullName.Replace("/", "\\")))
{
error_id = 1002;
error_msg = System.IO.Path.GetDirectoryName(UnZipFolder + "\\" + entry.FullName.Replace("/", "\\"));
System.IO.Directory.CreateDirectory(UnZipFolder + "\\" + entry.FullName.Replace("/", "\\"));
}
continue;
}
error_id = 1003;
error_msg = System.IO.Path.GetDirectoryName(UnZipFolder + "\\" + entry.FullName.Replace("/", "\\"));
entry.ExtractToFile(UnZipFolder + "\\" + entry.FullName.Replace("/", "\\"), true);
this.Invoke(new Action(() =>
{
progressBar1.Value = i+1;
}));
}
this.Invoke(new Action(() =>
{
progressBar1.Visible = false ;
progressBar1.Value = 0;
progressBar1.Maximum = 100;
}));
//System.IO.Compression.ZipFile.ExtractToDirectory(UpdateZipPath, UnZipFolder);
}
catch(Exception ex) {
this.Invoke(new Action(() =>
{
MessageBox.Show("升级包校验出错,升级中断["+error_id+"]=>"+ex.Message+"\r\n"+error_msg, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
RunFile(Application.StartupPath + "\\" + MainProcName, MainProcPram, null);
CloseApp();
}));
return;
}
//结束进程
ShowState("正在复制升级文件...");
Thread.Sleep(500);
if (System.IO.File.Exists(UnZipFolder + "\\" + old_filename))
{
bigFileOp.DelFileOrFolder(Application.StartupPath + "\\" + new_filename);
bigFileOp.CopyBigFile(UnZipFolder + "\\" + old_filename, Application.StartupPath + "\\" + new_filename);
RunFile(Application.StartupPath + "\\" + new_filename, "replace", null);
}
else {
RunFile(Application.StartupPath + "\\" + MainProcName, MainProcPram, null);
}
this.Invoke(new Action(() =>
{
CloseApp();
}));
break;
case "replace":
ShowState("正在替换升级文件...");
#region
KillMultiProcess(new List<string>() { old_filename });
MyXml.SelectNode("id", "KillProcList2");
var KillProcList2 = Base64ToStr(MyXml.GetAttrValue("Value", "")).Replace("\r", "").Split('\n');
var list_proc = new List<string>();
foreach (var proc in KillProcList2)
{
if (proc.Length == 0) { continue; }
list_proc.Add(proc);
}
KillMultiProcess(list_proc);
EndProcessByFolder(Application.StartupPath);
#endregion
ShowState("正在更新文件...");
this.Invoke(new Action(() =>
{
progressBar1.Visible = true;
}));
var result= bigFileOp.CopyFolderByProgress(UnZipFolder, Application.StartupPath);
this.Invoke(new Action(() =>
{
progressBar1.Visible = false;
}));
this.Invoke(new Action(() =>
{
if (result < 0)
{
var files = "";
for (int f = 0; f < bigFileOp.ErrFilesList.Count; f++)
{
if(f<=10)
{
files += bigFileOp.ErrFilesList[f] + "\r\n";
}
}
MessageBox.Show("新版文件替换失败。\r\n"+ files.Trim(), "更新失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
CloseApp();
}
RunFile(Application.StartupPath + "\\" + old_filename, "del", null);
CloseApp();
}));
break;
case "del":
ShowState("正在删除升级残余文件...");
bigFileOp.DelFileOrFolder(Application.StartupPath + "\\" + new_filename);
bigFileOp.DelFileOrFolder(Application.StartupPath + "\\Update");
bigFileOp.DelFileOrFolder(Application.StartupPath + "\\tmp.updx");
RunFile(Application.StartupPath + "\\" + MainProcName, MainProcPram, null);
this.Invoke(new Action(() =>
{
CloseApp();
}));
break;
}
}
else
{
CloseApp();
}
}
private void BigFileOp_OnFolderProgress(long curValue, long totalValue, double percent, long Speed = -1, object Tag = null)
{
this.Invoke(new Action(() =>
{
var int_percent= Convert.ToInt32(percent*100);
if (int_percent < 100)
{
progressBar1.Value = int_percent;
}
else
{
progressBar1.Value = 100;
}
}));
}
private void Frmmain_Load(object sender, EventArgs e)
{
EndProcessByFolder(Application.StartupPath);
}
private void Frmmain_Shown(object sender, EventArgs e)
{
var th = new Thread(StartUpdate);
th.Start();
}
private void Frmmain_FormClosing(object sender, FormClosingEventArgs e)
{
if (IsRunning) { e.Cancel = true; }
}
}
}