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]; } } /// /// /// public enum ShowCommands : int { /// /// /// SW_HIDE = 0, /// /// /// SW_SHOWNORMAL = 1, /// /// /// SW_NORMAL = 1, /// /// /// SW_SHOWMINIMIZED = 2, /// /// /// SW_SHOWMAXIMIZED = 3, /// /// /// SW_MAXIMIZE = 3, /// /// /// SW_SHOWNOACTIVATE = 4, /// /// /// SW_SHOW = 5, /// /// /// SW_MINIMIZE = 6, /// /// /// SW_SHOWMINNOACTIVE = 7, /// /// /// SW_SHOWNA = 8, /// /// /// SW_RESTORE = 9, /// /// /// SW_SHOWDEFAULT = 10, /// /// /// SW_FORCEMINIMIZE = 11, /// /// /// 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); /// /// /运行文件 /// /// /// /// /// /// 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); /// /// 获取进程路径 /// /// /// 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 list= new List(); 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 list = new List(); 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 list) { var process = Process.GetProcesses(); for (int i = 0; i < list.Count; i++) { EndProcess(list[i]); } } /// /// Base64转字符串 /// /// /// 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.SkipSameFiles = false; 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("/", "\\")); var is_same = false; try { if (bigFileOp.SkipSameFiles) { var topath = Application.StartupPath + "\\" + entry.FullName.Replace("/", "\\").Trim('\\'); if (System.IO.File.Exists(topath)) { var info = new +.IO.FileInfo(topath); if (info.Length == entry.Length && info.LastWriteTime == entry.LastWriteTime) { is_same = true; } } } } catch { } if (!is_same) { 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() { old_filename }); MyXml.SelectNode("id", "KillProcList2"); var KillProcList2 = Base64ToStr(MyXml.GetAttrValue("Value", "")).Replace("\r", "").Split('\n'); var list_proc = new List(); foreach (var proc in KillProcList2) { if (proc.Length == 0) { continue; } list_proc.Add(proc); } KillMultiProcess(list_proc); EndProcessByFolder(Application.StartupPath); Thread.Sleep(1000); #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; } } } }