读了这位博主的内容有所启发
https://blog.csdn.net/hzfw2008/article/details/106991629
金蝶补丁一般安装过后,都会进行解包,分两部分,第一部分为完整解包,第二部分为使用备份包
先讲第二部分,使用的备份包,也就这里有用,不是全系列产品完整的包补丁内容。
比如,k3 wise 15.0 PT124991包,只需要更新 一个exe和VER内容,其他不需要的东东,不在此处体现,在完整包里面体现。
Kingdee_SP_Install_Log_PT124991.log,为安装日志,从而可以用来参考复制到哪里。
********* Start installation: 6-17-2020 09:31:54 ********* call K3DCOMManageStop.exe File : C:Program Files (x86)KingdeeK3ERPK3ClassDEFINENewUSER.exe FileName : K3ClassDEFINENewUSER.exe Path : C:Program Files (x86)KingdeeK3ERP Backup File : C:Program Files (x86)KingdeeK3ERPK3ClassDEFINENewUSER.exe Replace File: C:Program Files (x86)KingdeeK3ERPK3ClassDEFINENewUSER.exe File : C:Program Files (x86)KingdeeK3ERPKDSYSTEMK3MFYGLMakeVoucher.VBR FileName : K3MFYGLMakeVoucher.VBR Path : C:Program Files (x86)KingdeeK3ERPKDSYSTEM Backup File : C:Program Files (x86)KingdeeK3ERPKDSYSTEMK3MFYGLMakeVoucher.VBR Replace File: C:Program Files (x86)KingdeeK3ERPKDSYSTEMK3MFYGLMakeVoucher.VBR ------- Finish Copying File(s): 6-17-2020 09:32:34 ------- call BatAndExe.bat call K3DCOMManageStart.exe ********** End installation: 6-17-2020 09:32:37 **********
现在讲第一部分
还以PT124991补丁包举例子,这里面是次补丁涉及到的所有,不仅局限与客户端、服务端,还有其他等等,也不用仔细研究这个,总之是完整解包的内容。
KDPatchs这个文件夹其实木有卵用。
因为新的金蝶补丁全部加壳,在服务期内的通过验证后,可以打补丁。超过服务期的,正常是打不了的,可以通过如下方法变通处理下:
1、找一台已经装好补丁的客户端(如果找不到,那就用金蝶服务器也行)。将客户端下面如下2个目录的文件夹打包压缩备用。如果提示被占用,请先使用任务管理器结束K3或者KD打头的进程;
2、在新的系统上按照标准方法安装金蝶K3客户端。跑一遍中间层组件注册;
3、将上面打包压缩的2个文件夹覆盖掉新系统的同名文件夹;
4、打开新系统的该目录,使用管理员权限运行如下2个批处理文件,重新进行组件注册;
这两个bat,一个是注册中间件的,一个是注册产品的。总之重新注册一下就好。
有人该问了,控制面板卸载软件里面有木有补丁包信息,已经注册表里面有木有,这个肯定木有了,相当于绿色了。这就涉及到第5条的内容,第5条继续说。
5、运行桌面K3图标即可正常使用金蝶客户端。
这里就遇见坑了。什么坑呢,只要打开金蝶就自己下载补丁包进行安装,这不扯淡了嘛。本来拷贝过来的文件里面就有补丁。其实呢是因为一个自动打补丁的东东,只要你打开金蝶就开始检测注册表里面是不是已经安装过这个补丁了,没有就下载进行安装。
这么蛋疼的事情,就不备份已经安装过补丁电脑的相关注册表了,直接干掉这个自动补丁安装程序就好了。
Kingdee.K3.BaseNet.UpdatePatchApp.exe
这个程序在金蝶安装根目录里面,将其删掉,或者改名就好。
Program
using System; using System.Windows; using Kingdee.K3.BaseNet.AutoUpdatePatchCommon; namespace Kingdee.K3.BaseNet.UpdatePatchApp { // Token: 0x02000003 RID: 3 public class Program { // Token: 0x06000005 RID: 5 RVA: 0x000021D0 File Offset: 0x000003D0 [STAThread] private static void Main(string[] args) { Log.WriteLog("进入客户端补丁升级工具Kingdee.K3.BaseNet.UpdatePatchApp.exe"); if (args == null || args.Length != 1) { Log.WriteLog("args == null || args.Length != 1,退出客户端补丁升级工具!"); return; } Log.WriteLog("外部传入客户端补丁升级工具参数:" + args[0]); new Application().Run(new ProgressWindow(args[0])); } } }
Common
using System; using System.Diagnostics; using System.Reflection; using Kingdee.K3.BaseNet.AutoUpdatePatchCommon; namespace Kingdee.K3.BaseNet.UpdatePatchApp { // Token: 0x02000002 RID: 2 public class Common { // Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250 public static string LoadKDString(string strText) { string result; try { Type typeFromProgID = Type.GetTypeFromProgID("K3BaseDataAccess.CMultiLanguage"); object target = Activator.CreateInstance(typeFromProgID); object[] args = new object[] { strText, "K3Base" }; result = (string)typeFromProgID.InvokeMember("LoadKDString", BindingFlags.Public | BindingFlags.InvokeMethod, null, target, args); } catch { Log.WriteLog("Kingdee.K3.BaseNet.UpdatePathApp.LoadKDString(),Error strText=" + strText); result = strText; } return result; } // Token: 0x06000002 RID: 2 RVA: 0x000020CC File Offset: 0x000002CC public static bool IsOpenAntivirus() { bool result = false; try { Process[] processesByName = Process.GetProcessesByName("360sd"); if (processesByName.Length == 0) { processesByName = Process.GetProcessesByName("360Tray"); if (processesByName.Length > 0) { Log.WriteLog("检测到客户端安装了360安全卫士"); result = true; } } else { Log.WriteLog("检测到客户端安装了360杀毒软件"); result = true; } } catch (Exception ex) { Log.WriteLog("判断是否开启杀毒软件报错IsOpenAntivirus:" + ex.ToString()); } return result; } // Token: 0x06000003 RID: 3 RVA: 0x00002144 File Offset: 0x00000344 public static void ClosedK3Proc(string strProcName) { try { Log.WriteLog(string.Format("检测K3进程{0}", strProcName)); Process[] processesByName = Process.GetProcessesByName(strProcName); int num = processesByName.Length; Log.WriteLog(string.Format("检测K3进程{0}有{1}个,下一步这些关闭进程", strProcName, num)); if (num > 0) { for (int i = 0; i < num; i++) { processesByName[i].Kill(); } } } catch (Exception ex) { Log.WriteLog(string.Format("强制关闭{0}主控台报错:{1}", strProcName, ex.ToString())); } } } }
ProgressWindow
using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Markup; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Threading; using Kingdee.K3.BaseNet.AutoUpdatePatchClient; using Kingdee.K3.BaseNet.AutoUpdatePatchCommon; namespace Kingdee.K3.BaseNet.UpdatePatchApp { // Token: 0x02000004 RID: 4 public class ProgressWindow : Window, IComponentConnector { // Token: 0x17000001 RID: 1 // (get) Token: 0x06000007 RID: 7 RVA: 0x00002228 File Offset: 0x00000428 // (set) Token: 0x06000008 RID: 8 RVA: 0x0000223A File Offset: 0x0000043A public string Message { get { return (string)base.GetValue(ProgressWindow.MessageProperty); } set { base.SetValue(ProgressWindow.MessageProperty, value); } } // Token: 0x17000002 RID: 2 // (get) Token: 0x06000009 RID: 9 RVA: 0x00002248 File Offset: 0x00000448 // (set) Token: 0x0600000A RID: 10 RVA: 0x0000225A File Offset: 0x0000045A public int ProgressValue { get { return (int)base.GetValue(ProgressWindow.ProgressValueProperty); } set { base.SetValue(ProgressWindow.ProgressValueProperty, value); } } // Token: 0x17000003 RID: 3 // (get) Token: 0x0600000B RID: 11 RVA: 0x0000226D File Offset: 0x0000046D // (set) Token: 0x0600000C RID: 12 RVA: 0x0000227F File Offset: 0x0000047F public int ProgressMaximum { get { return (int)base.GetValue(ProgressWindow.ProgressMaximumProperty); } set { base.SetValue(ProgressWindow.ProgressMaximumProperty, value); } } // Token: 0x0600000D RID: 13 RVA: 0x00002294 File Offset: 0x00000494 public ProgressWindow(string k3StartupProgromName) { try { this.m_lstNeedInstallPatch = this.GetNeesInstallPatchs(); if (this.m_lstNeedInstallPatch.Count == 0) { Log.WriteLog(string.Format("本客户端没有补丁需要安装,直接退出补丁更新工具", new object[0])); Application.Current.Shutdown(); } else { string text = ""; try { text = PatchVerify.GetRegistryKeyValue("", "IsAuto"); } catch (Exception) { } Log.WriteLog("读取注册表 IsAuto=" + text + "," + ((text == "1") ? "当前机器正在安装补丁,请稍后再尝试!。" : "空值可进行补丁安装")); if (text == "1") { Process[] processesByName = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName); if (processesByName.Length > 1) { MessageBox.Show(Common.LoadKDString("客户端正在更新补丁,请稍后再尝试!"), Common.LoadKDString("金蝶提示"), MessageBoxButton.OK, MessageBoxImage.Asterisk); Application.Current.Shutdown(); return; } } this.InitializeComponent(); base.DataContext = this; this._k3StartupProgromName = k3StartupProgromName; } } catch (Exception ex) { Log.WriteLog(string.Format("补丁更新工具报错,直接退出:{0}", ex.ToString())); } } // Token: 0x0600000E RID: 14 RVA: 0x000024AC File Offset: 0x000006AC private void UpdatePatchs() { bool flag = false; try { PatchVerify.SetIsAutoRegedit("1"); } catch (Exception ex) { Log.WriteLog("读取注册表" + ex.ToString()); } Action<string> method = delegate(string message) { this.Message = message; }; Action<int> method2 = delegate(int progressValue) { this.ProgressValue = progressValue; }; Action<int> method3 = delegate(int progressMaximum) { this.ProgressMaximum = progressMaximum; }; Action method4 = delegate() { Storyboard storyboard = base.Resources["ClosedStoryboard"] as Storyboard; storyboard.Completed += delegate(object A_1, EventArgs A_2) { base.Close(); }; storyboard.Begin(); }; try { Thread.Sleep(3000); ProcessStartInfo processStartInfo = null; Process process = null; int num = 0; bool flag2 = true; Func<bool> func = delegate() { process = new Process { StartInfo = processStartInfo }; process.Start(); bool result = process.WaitForExit(1800000); process.Close(); return result; }; List<string> lstNeedInstallPatch = this.m_lstNeedInstallPatch; base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method3, lstNeedInstallPatch.Count * 4); int num2 = 0; int count = lstNeedInstallPatch.Count; foreach (string text in lstNeedInstallPatch) { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method2, num2 * 4); string[] array = text.Split(new char[] { '|' }); bool flag3 = array[0] == "0"; string patchNo = array[1]; string arg = string.Concat(new object[] { Common.LoadKDString("正在安装第"), num2 + 1, Common.LoadKDString("个补丁"), patchNo, Common.LoadKDString(",共"), count, Common.LoadKDString("个,请稍候...") }); PatchTransfer patchTransfer = new PatchTransfer(); string text2 = Path.Combine(SocketTransferData.PatchDiretory, string.Format("{0}.rar", patchNo)); base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method2, num2 * 4 + 1); base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, arg); patchTransfer.DownloadPatchToServer(string.Format("{0}.rar", patchNo), ref num); if (flag2) { string text3 = Path.Combine(Path.Combine(SocketTransferData.PatchDiretory, patchNo), string.Format("{0}.exe", patchNo)); if (flag3 && PatchVerify.IsPatchInstallLocal(patchNo)) { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, patchNo + Common.LoadKDString("已安装,不进行重复安装")); Log.WriteLog(string.Format("{0}已安装,不进行重复安装", patchNo)); continue; } string text4 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "WinRAR.exe"); Path.GetDirectoryName(text4); FileInfo fileInfo = new FileInfo(text2); string arguments = string.Format("x "{0}" "{1}" -y -ibck -inul", text2, fileInfo.DirectoryName); if (File.Exists(text2)) { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method2, num2 * 4 + 2); processStartInfo = new ProcessStartInfo { FileName = text4, Arguments = arguments, WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = false, CreateNoWindow = true, RedirectStandardError = true, RedirectStandardInput = true, RedirectStandardOutput = true, Verb = "runas" }; base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, Common.LoadKDString("正在解压") + patchNo); if (func()) { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, patchNo + Common.LoadKDString("已解压")); Log.WriteLog(string.Format("{0}已解压", patchNo)); PatchVerify.DeleteRegedit(patchNo); if (File.Exists(text3)) { processStartInfo = new ProcessStartInfo { FileName = text3, WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = false, CreateNoWindow = true, Arguments = " -slient", Verb = "runas" }; base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, arg); base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method2, num2 * 4 + 3); if (func()) { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, Common.LoadKDString("已安装") + patchNo); Log.WriteLog(string.Format("{0}已安装", patchNo)); if (!flag3) { if ((from dr1 in PatchInstall.dt_InstalledPatch where dr1.PatchNo == patchNo select 1).Count<int>() == 0) { DataSet1.DT_InstalledPatchRow dt_InstalledPatchRow = PatchInstall.dt_InstalledPatch.NewDT_InstalledPatchRow(); dt_InstalledPatchRow.PatchNo = patchNo; PatchInstall.dt_InstalledPatch.AddDT_InstalledPatchRow(dt_InstalledPatchRow); PatchInstall.dt_InstalledPatch.WriteXml(PatchInstall.installedPatchFilePath); } Log.WriteLog(string.Format("{0}已更新补丁状态", patchNo)); } } else { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, patchNo + Common.LoadKDString("安装失败")); Log.WriteLog(string.Format("{0}安装失败", patchNo)); File.Delete(text3); if (flag3) { flag2 = false; continue; } continue; } } else { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, Common.LoadKDString("无法找到补丁文件") + text3); Log.WriteLog(string.Format("无法找到补丁文件 {0}", text3)); } } else { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, patchNo + Common.LoadKDString("解压失败")); Log.WriteLog(string.Format("{0}解压失败", patchNo)); if (flag3) { flag2 = false; continue; } continue; } } else { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, Common.LoadKDString("无法找到补丁压缩包文件") + text2); Log.WriteLog(string.Format("无法找到补丁压缩包文件 {0}", text2)); } } else { base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, Common.LoadKDString("由于前置补丁安装异常,未安装") + patchNo); Log.WriteLog(string.Format("由于前置补丁安装异常,{0}未安装", patchNo)); if (!flag3) { flag2 = true; } } base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method2, num2 * 4 + 4); num2++; } base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method, Common.LoadKDString("更新完成,启动K3WISE控制台")); flag = true; } catch (Exception ex2) { flag = false; Log.WriteLog(ex2.ToString()); } finally { try { PatchVerify.SetIsAutoRegedit(""); } catch (Exception ex3) { Log.WriteLog("读取注册表" + ex3.ToString()); } Thread.Sleep(1000); base.Dispatcher.Invoke(DispatcherPriority.SystemIdle, method4); if (!flag) { MessageBoxResult messageBoxResult = MessageBox.Show(Common.LoadKDString("补丁安装过程中出现异常,可能导致K3使用过程中出现异常,请联系管理员。 是否要继续打开K3?"), Common.LoadKDString("金蝶提示"), MessageBoxButton.YesNo, MessageBoxImage.Exclamation); if (messageBoxResult == MessageBoxResult.Yes) { flag = true; } } if (flag) { string text5 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, this._k3StartupProgromName + ".exe"); Log.WriteLog("补丁更新完成,启动主控台,启动路径:" + text5); if (!File.Exists(text5)) { MessageBox.Show(text5 + Common.LoadKDString("路径不正确!")); } ProcessStartInfo startInfo = new ProcessStartInfo { FileName = text5, WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = false, Arguments = "updated", Verb = "runas" }; Process process2 = new Process { StartInfo = startInfo }; process2.Start(); } } } // Token: 0x0600000F RID: 15 RVA: 0x00002D30 File Offset: 0x00000F30 private List<string> GetNeesInstallPatchs() { List<string> list = new List<string>(); try { bool flag = PatchInstall.IsNeedUpdatePatch(); if (flag) { list = PatchInstall.m_NeedInstallPatchList; if (list == null) { Log.WriteLog(string.Format("方法GetNeesInstallPatchs判断客户端是否有补丁需要安装得出值为null", new object[0])); return list; } int count = list.Count; Log.WriteLog(string.Format("方法GetNeesInstallPatchs判断客户端是否有补丁需要安装检测到有{0}个补丁需要安装", count)); for (int i = count - 1; i >= 0; i--) { string text = list[i]; string[] array = text.Split(new char[] { '|' }); string text2 = array[1]; bool flag2 = PatchVerify.IsPatchInstallLocal(text2); if (flag2) { list.RemoveAt(i); } } } } catch (Exception ex) { Log.WriteLog(string.Format("方法GetNeesInstallPatchs判断客户端是否有补丁需要安装报错:{0}", ex.ToString())); } return list; } // Token: 0x06000010 RID: 16 RVA: 0x00002E28 File Offset: 0x00001028 private void Window_Loaded(object sender, RoutedEventArgs e) { try { int count = this.m_lstNeedInstallPatch.Count; if (count > 0) { Common.ClosedK3Proc(this._k3StartupProgromName); (base.Resources["OpenStoryboard"] as Storyboard).Begin(); this.Main.OpacityMask = (base.Resources["ClosedBrush"] as LinearGradientBrush); Log.WriteLog(string.Format("客户端补丁更新工具最终结果检测到有{0}个补丁需要在本客户端安装,马上进入安装阶段", count)); if (Common.IsOpenAntivirus()) { MessageBox.Show(Common.LoadKDString("安装补丁前请关闭杀毒软件!"), Common.LoadKDString("金蝶提示"), MessageBoxButton.OK, MessageBoxImage.Exclamation); } new Thread(new ThreadStart(this.UpdatePatchs)).Start(); } else { Log.WriteLog(string.Format("本客户端没有补丁需要安装", new object[0])); } } catch (Exception ex) { Log.WriteLog(string.Format("客户端补丁更新工具Kingdee.K3.BaseNet.UpdatePatchApp.exe报错:{0}", ex.ToString())); } } // Token: 0x06000011 RID: 17 RVA: 0x00002F24 File Offset: 0x00001124 [DebuggerNonUserCode] [GeneratedCode("PresentationBuildTasks", "4.0.0.0")] public void InitializeComponent() { if (this._contentLoaded) { return; } this._contentLoaded = true; Uri resourceLocator = new Uri("/Kingdee.K3.BaseNet.UpdatePatchApp;component/progresswindow.xaml", UriKind.Relative); Application.LoadComponent(this, resourceLocator); } // Token: 0x06000012 RID: 18 RVA: 0x00002F54 File Offset: 0x00001154 [GeneratedCode("PresentationBuildTasks", "4.0.0.0")] [EditorBrowsable(EditorBrowsableState.Never)] [DebuggerNonUserCode] void IComponentConnector.Connect(int connectionId, object target) { switch (connectionId) { case 1: ((ProgressWindow)target).Loaded += this.Window_Loaded; return; case 2: this.Screen = (Grid)target; return; case 3: this.Main = (Border)target; return; default: this._contentLoaded = true; return; } } // Token: 0x04000001 RID: 1 private string _k3StartupProgromName; // Token: 0x04000002 RID: 2 public static readonly DependencyProperty MessageProperty = DependencyProperty.Register("Message", typeof(string), typeof(ProgressWindow), new PropertyMetadata(Common.LoadKDString("开始更新"))); // Token: 0x04000003 RID: 3 public static readonly DependencyProperty ProgressValueProperty = DependencyProperty.Register("ProgressValue", typeof(int), typeof(ProgressWindow), new PropertyMetadata(0)); // Token: 0x04000004 RID: 4 public static readonly DependencyProperty ProgressMaximumProperty = DependencyProperty.Register("ProgressMaximum", typeof(int), typeof(ProgressWindow), new PropertyMetadata(100)); // Token: 0x04000005 RID: 5 private List<string> m_lstNeedInstallPatch = new List<string>(); // Token: 0x04000006 RID: 6 internal Grid Screen; // Token: 0x04000007 RID: 7 internal Border Main; // Token: 0x04000008 RID: 8 private bool _contentLoaded; } }
至于有木有真正的打上补丁,自己去实验吧。总之我是验证过了,包括补丁包里面的内容md5值都已经比对过,和安装过补丁的电脑文件md5值一样。
有点拗口,这里可以忽略。
使用的系统也忽略哈,Linux是我的主战场,一条md5sum进行计算,多么方便。